diff --git a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd index f0286b2..73ed848 100644 --- a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd +++ b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd @@ -24,13 +24,11 @@ output: # 0.0 Preliminaries. -This report is generated from an R Markdown file that includes all the R code necessary to produce the results described and embedded in the report. Code blocks can be suppressed from output for readability using the command code `{R, echo=show}` in the code block header. If `show <- FALSE` the code block will be suppressed; if `show <- TRUE` then the code will be show. ```{r} # Set to TRUE to expand R code blocks; set to FALSE to collapse R code blocks show <- TRUE ``` - Executing this R notebook requires some subset of the following packages: * `ggplot2` @@ -45,6 +43,7 @@ Executing this R notebook requires some subset of the following packages: * `caret` * `ggrepel` * `ggtern` +* `geosphere` These will be installed and loaded as necessary (code suppressed). @@ -118,6 +117,10 @@ if (!require("ggtern")) { library(ggrepel) } +if (!require("geosphere")) { + install.packages("geosphere") + library(geosphere) +} ``` # 1.0 Project Introduction @@ -136,28 +139,25 @@ This report is organize as follows: * Section 6.0 Overall conclusions and suggestions -* Section 7.0 Appendix This section describe the following additional works that may be helpful in the future work: *list subjects*. +* Section 7.0 Appendix This section describe the following additional works that may be helpful in the future work: Additional Soil Composition Plots of LIBS and PIXL # 3.0 Finding 1: PIXL and LIBS Matching -_Give a highlevel overview of the major finding. What questions were your trying to address, what approaches did you employ, and what happened?_ - Firstly, we will be taking a look at how PIXL and LIBS correspond. Our group found very early in our research that there wasn't a feature among them that can be used to match the data sets. For example, the columns of PIXL are organized by latitude and longitude as well as sample number (1-16), sample name, and abrasion name. Unfortunately, LIBS wasn't sorted the same way. LIBS was organized by the sol that the sample was taken at. LIBS is broken up into many different types of samples as well, including the fact it carries around earth reference data to be used in comparing with different sample sites. That being said, in order to match PIXL targets to corresponding LIBS samples, Margo and I created a new data set that added another metadata feature to PIXL (latitude and longitude coordinates) which we obtained from the Analyst's Notebook. Once this was added in, we realized that the longitude and latitude didn't really match. So Margo created a distance function to match LIBS samples to PIXL targets based on whatever distance a person specifies. Originally, we set it to be rounded to three thousandths and match based on that. This helped answer the question of how can we correlate the LIBS and PIXL data sets to be able to plot them on the same axis of whatever plot is trying to be created. I was curious to see how close PIXL targets were to LIBS sample sites as well as how many LIBS samples would be associated with a PIXL target perhaps with a radius of 7 or 10 meters. ## 3.1 Data, Code, and Resources -Here is a list data sets, codes, that are used in your work. Along with brief description and URL where they are located. +1. peterc_finalProjectF24.Rmd (with knit pdf and html) is this notebook. +[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) -1. peterc-finalProjectF24.Rmd (with knit pdf and html) is this notebook. -[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) 2. v1_libs_to_sample.Rds is the combined data set of PIXL and LIBS that includes the distance from a PIXL abrasion to a LIBS sample. [https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentData/v1_libs_to_sample.Rds](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentData/v1_libs_to_sample.Rds). -Firstly, we set the number of meters distance threshold between a PIXL abrasion and LIBS sample. Within the v1_libs_to_sample.Rds, which Margo and I collaborated on there is a distance variable that is set via a function that Margo created to measure the distance between a PIXL abrasion and LIBS sample using their latitude and longitude coordinates. +Firstly, we set the number of meters distance threshold between a PIXL abrasion and LIBS sample. Within the v1_libs_to_sample.Rds, which Margo and I collaborated on there is a distance variable that is set via a function that Margo created to measure the distance between a PIXL abrasion and LIBS sample using their latitude and longitude coordinates. 7 meters is the best metric because that is the maximum distance the LIBS instrument can accurately collect data from. ```{r} meters <- 7 ``` @@ -210,8 +210,6 @@ ggplot(data = df_distance_filter) + theme( plot.caption = element_text(hjust = 0) # Aligns caption to the left ) - -#add legend for PIXL idk why it's not working ``` When looking at this plot, the data frame of the filtered LIBS data (df_distance_filter) based on distances to a PIXL abrasion less than or equal to 7 meters finds 3 LIBS samples corresponding to Alfalfa, 2 corresponding to Bellegrade, 3 corresponding to Dourbes, 7 corresponding to Novarupta, 4 corresponding to Quartier, and 9 corresponding to Thornton Gap. @@ -220,16 +218,13 @@ When looking at this plot, the data frame of the filtered LIBS data (df_distance I believe my findings make it very easy for researchers and scientists to have a visualization of PIXL and LIBS samples that they want to see based on what max distance they are focusing on when examining PIXL and LIBS together. For future work, I think as more coordinates and data is added to the LIBS and PIXL data sets as they become available from NASA this will continue to be built upon and although it isn't super complicated of a plot, it provides a very necessary context to visualize PIXL and LIBS. I didn't find many limitations in this plot as it basically is only providing an easy visual of the PIXL and LIBS data together. # 4.0 Finding 2: Soil Composition Analysis -_Give a highlevel overview of the major finding. What questions were your trying to address, what approaches did you employ, and what happened?_ - -Using the LIBS and PIXL combined data set, I created a plot of the composition percentages of chemical compounds such as Si02, K20, etc. using log scaling to compare the compositions of a PIXL abrasion and the corresponding LIBS sample compositions (based on the LIBS samples for x distance away from a PIXL abrasion). The question I was trying to answer was how does the LIBS data of a certain area compare to the PIXL data of that area? By looking at the composition of the soil in certain locations, we can compare the differences in the PIXL abrasion and relating LIBS samples for a certain area utilizing the same data set (v1_libs_to_sample.Rmd). In order to accomplish this, +Using the LIBS and PIXL combined data set, I created a plot of the composition percentages of chemical compounds such as Si02, K20, etc. using log scaling to compare the compositions of a PIXL abrasion and the corresponding LIBS sample compositions (based on the LIBS samples for x distance away from a PIXL abrasion). The question I was trying to answer was how does the LIBS data of a certain area compare to the PIXL data of that area? Are there many differences between locations (meaning which abrasions and their corresponding LIBS targets are different and in what ways, do igneous vs. sedimentary show a pattern?). In order to accomplish this, we will use a distance function to filter within 7 meters of distance between a PIXL sample and LIBS target (this is the maximum distance of accuracy based on NASA's information on LIBS spectroscopy machinery). Then, the data for earth quartile references (first and third quartiles and median), PIXL abrasion chemical composition, and corresponding LIBS target chemical compositions will be plotted based on the chosen PIXL abrasion (only one abrasion is plotted at a time). ## 4.1 Data, Code, and Resources -Here is a list data sets, codes, that are used in your work. Along with brief description and URL where they are located. 1. peterc_finalProjectF24.Rmd (with knit pdf and html) is this notebook. -[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) +[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) 2. peterc_assignment5.Rmd (with knit pdf and html) which is my previous notebook. [https://github.rpi.edu/DataINCITE/DAR-Mars-F24/tree/main/StudentNotebooks/Assignment05/peterc_assignment05.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/tree/main/StudentNotebooks/Assignment05/peterc_assignment05.Rmd]) @@ -243,7 +238,7 @@ Here is a list data sets, codes, that are used in your work. Along with brief de 4. LIBS_training_set_quartiles.Rds is the data with earth quartile reference data. [https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/Data/LIBS_training_set_quartiles.Rds](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/Data/LIBS_training_set_quartiles.Rds). -To prepare the data, I start by loading in the LIBS data. Then, we drop the standard deviation columns and sum of percentage columns leaving us with just the weighted composition in terms of numerical data. We also remove the scct values, as those values are the ones that are earth reference samples that Perserverance carries with it. Therefore, they will not be very relevant when plotting the LIBS data as we are focused on the Mars soil compositions. +To prepare the data, I start by loading in the LIBS data. Then, we drop the standard deviation columns and sum of percentage columns leaving us with just the weighted composition in terms of numerical data. We also remove the scct values, as those values are the ones that are earth reference samples that Perseverance carries with it. Therefore, they will not be very relevant when plotting the LIBS data as we are focused on the Mars soil compositions. ```{r} #Earth quartiles @@ -273,7 +268,7 @@ Set meters and chosen abrasion to act as a slider in the 2d app. #Choose max distance variable between PIXL and LIBS data meters = 7 #Choose PIXL abrasion you want to look at -abrasion_name = "Alfalfa" +abrasion_name = "ThorntonGap" ``` Next, we load in the PIXL data. We remove the atmospheric sample and only select one PIXL sample of each abrasion. @@ -337,7 +332,7 @@ libs.matrix<-libs.matrix[,c(1:2,4:9,3)] libs.matrix<-cbind("Abrasion"=0,libs.matrix) libs.matrix<-libs.matrix%>% mutate(Abrasion = ifelse(target%in%Alfalfa,"Alfalfa", - ifelse(target %in% Bellegrade, "Belegrade", + ifelse(target %in% Bellegrade, "Bellegrade", ifelse(target %in% BerryHollow, "Berry Hollow", ifelse(target %in% Dourbes, "Dourbes", ifelse(target %in% Novarupta, "Novarupta", @@ -369,20 +364,22 @@ pixllibs.df<-rbind(pixl.df,libs.matrix) ## 4.2 Contribution -Some of the data manipulating work was Margo's, such as the distance function. In terms of pivoting the data frame and the other steps of the preprocessing is my own work. The manipulating below to plot the line soil composition plots is my own. +Some of the data manipulating work was Margo's, such as the distance function. In terms of pivoting the data frame and the other steps of the preprocessing is my own work. The manipulating and setup of data below to plot the line soil composition plots is my own. Margo and I worked together to create the data sets used. In our presentation, David was able to create a facid grid to compliment my single abrasion analysis which showed the average LIBS target chemical composition and corresponding PIXL abrasion composition. This was done in RShiny and implemented in the app, so I felt that redoing the same plot wouldn't be necessary. I focused on plotting one specific abrasion to provide more in depth analysis of one abrasion and the surrounding area since David was able to provide more context and plot the PIXL abrasions all at once. ## 4.3 Methods Description When deciding how to approach the concept of building soil composition plots of each PIXL abrasion and the corresponding LIBS targets within a certain distance maximum, I decided the best way was to start with the original data sets and modify them as needed. For the actual plot, the best way to format the data correctly is to pivot it, as I need the x axis to be the column names in the current data frame we have (SiO2 and other compositions) and the y axis to be the weighted composition values. We also need an indicator of if the data is from PIXL or LIBS, which also is helpful for building the line plots. -Users will have to set the distance variable in order to choose the max distance between PIXL abrasions and LIBS targets. This can vastly change the number of lines on the plots which can help prevent overcrowded plots. Users also can set a variable to choose a specific PIXL abrasion and corresponding LIBS targets, which is easier to interpret as plotting all of the LIBS and PIXL composition information on line plots leads to very condensed graphs that are hard to read. +Users will have to set the distance variable in order to choose the maximum distance between PIXL abrasions and LIBS targets. This can vastly change the number of lines on the plots which can help prevent overcrowded plots. Users also can set a variable to choose a specific PIXL abrasion and corresponding LIBS targets, which is easier to interpret as plotting all of the LIBS and PIXL composition information on line plots leads to very condensed graphs that are hard to read. ## 4.4 Result and Discussion -First, we will turn the earth quartile information into a long data frame (meaning pivoting the columns into the values). +First, we will turn the earth quartile information into a long data frame (meaning pivoting the columns into the values) and only select the first and third quartile rows. ```{r} # Earth quartiles -earthquartiles_long <- earthquartiles.df %>% +filtered_rows <- earthquartiles.df %>% + filter(`Training set Quartiles` %in% c("1st", "3rd", "Med")) +earthquartiles_long <- filtered_rows %>% pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage") earthquartiles_long <- earthquartiles_long %>% rename(Quartiles = `Training set Quartiles`) @@ -402,10 +399,10 @@ desired_order <- c("SiO2", "Al2O3", "FeOT", "MgO", "CaO", "Na2O", "K2O", "TiO2") pixllibs_long$Compound <- factor(pixllibs_long$Compound, levels = desired_order) ``` -For the plot, we use ggplot to plot the pixllibs_long data frame we created. The plot is colored by if the line is a PIXL abrasion's composition or a LIBS target's composition. We also add a layer with the earth quartile information, which is the dotted lines. +For the plot, we use ggplot to plot the pixllibs_long data frame we created. The plot is colored by if the line is a PIXL abrasion's composition or a LIBS target's composition. We also add a layer with the earth quartile information, which is the dotted lines. The weight percentages on the y axis are log scaled as it makes the plot more readable, but this can be edited (will be added as a toggle in the app). ```{r} # Map the PIXL/LIBS column to color and use target_name to differentiate lines -ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) + +suppressWarnings(ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) + geom_line() + geom_point() + scale_y_continuous(trans='log10') + @@ -416,24 +413,30 @@ ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsor x = "Chemical Compound", y = "Weight Percentage", color = "Measurement Type", - linetype = "Earth Quartiles") + + linetype = "Quartiles", + caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") + scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) + - theme_minimal() + annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) + + annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) + + annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)+ + theme_minimal()+ + # Center the caption on the left side + theme( + plot.caption = element_text(hjust = 0) # Aligns caption to the left + )) + ``` -I still plan to update and try using the ggplotlay feature to incorporate all the abrasions and data onto one grid of line plots. I also am going to add plots where the mean is taken of all the LIBS targets that correspond to a PIXL abrasion so the plot will only have one LIBS line and one PIXL line (along with the references), this is all just for the draft. I also need to only add certain quartile information and label them, this is just a placeholder of the previous plot. Also maybe will add in SCCT values as references, not sure if they are super relevant or how to sort them. +To save space in this notebook, I did not plot each abrasion (based on chosen abrasion variable name). In comparing each PIXL abrasion and the corresponding LIBS targets, I found that the PIXL abrasions corresponding to igneous had very similar plots, while the PIXL abrasions corresponding to sedimentary had very similar plots. The igneous/sedimentary indicator is shown in the PIXL data. An interesting thing to note is that for some abrasions, like Alfalfa and ThorntonGap, the chemical compositions of both PIXL samples in the abrasion are the same. For other abrasions, like Bellegrade, the chemical compositions of the PIXL samples in the Bellegrade abrasion differ. Also, many of the plots had a few points with very low K2O which seems like a major outlier. ## 4.5 Conclusions and Future Work -This finding can be used by geologists to analyze what different soil compositions around different PIXL abrasions can mean for life on Mars. For example, oxide presence doesn't necessarily indicate life, but it could indicate biological or chemical life processes. For example, CaO can indicate the presence of old biological material like shells or fossils. --Add more about future work, not sure what else to include +This finding can be used by geologists to analyze what different soil compositions around different PIXL abrasions can mean for life on Mars. For example, oxide presence doesn't necessarily indicate life, but it could indicate biological or chemical life processes. For example, CaO can indicate the presence of old biological material like shells or fossils. For future work, I would like to see why certain abrasions differ in their PIXL core sample composition. Is this based on the research done by scientists in selecting specific abrasions and trying to obtain differing samples for abrasions in certain areas? Or is this by chance? Or is it simply showing more rock variety or weathering the certain abrasions? # 5.0 Finding 3: Analyzing Cation Combinations using LIBS and PIXL matched data -Using the LIBS and PIXL combined data set, we created a ternary plot to show the distribution of LIBS samples sorted by what PIXL abrasion they are closest to (based on a chosen distance variable). Much of the data preprocessing is similar to Finding 1 which we will repeat here. However, the goal here is to analyze how different groups of LIBS samples (colored by matching PIXL abrasion) differ by cation composition. +Using the LIBS and PIXL combined data set, we created a ternary plot to show the distribution of LIBS samples sorted by what PIXL abrasion they are closest to (based on a chosen distance variable). Much of the data preprocessing is similar to Finding 1 which we will repeat here. It will involve using a distance function to correlate LIBS targets with PIXL samples, matching the data based on the closest PIXL sample, and plotting the LIBS data (colored by corresponding PIXL abrasion) and the PIXL abrasions on a ternary plot. The goal here is to analyze how different groups of LIBS samples (colored by matching PIXL abrasion) differ by cation composition. Do igneous vs. sedimentary rock play a roll in composition tendencies and show a pattern? By looking at the composition of the soil in certain locations, we can compare the differences in the PIXL abrasion and relating LIBS samples for a certain area by combining the LIBS and PIXL data sets. In order to accomplish this, we will use a distance function to filter within 7 meters of distance between a PIXL sample and LIBS target (this is the maximum distance of accuracy based on NASA's information on LIBS spectroscopy machinery). ## 5.1 Data, Code, and Resources -Here is a list data sets, codes, that are used in your work. Along with brief description and URL where they are located. - -1. peterc-finalProjectF24.Rmd (with knit pdf and html) is this notebook. -[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) +1. peterc_finalProjectF24.Rmd (with knit pdf and html) is this notebook. +[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) 2. supercam_libs_moc_loc.Rds which is the original LIBS data given to our research group. [https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/Data/supercam_libs_moc_loc.Rds](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/Data/supercam_libs_moc_loc.Rds) @@ -467,7 +470,7 @@ libstargets.df<-libs.df[,c(1,3,4,5)] libstargets.df<-distinct(libstargets.df) ``` -Load in PIXL data +Next, we will load in the PIXL data that is in StudentData as the pixl_sol_coordinates data frame includes the latitude, longitude, and sol of each PIXL sample. We only include the metadata as this is all that is necessary for the distance function (the sample name and coordinates of the sample) as well as only one PIXL sample from each abrasion. As each abrasion has 2 PIXL samples taken, they have the same latitude and longitude and therefore it is unnecessary to use both. We also remove the atmospheric sample. ```{r} #read in pixl data with lat/long pixl.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/StudentData/pixl_sol_coordinates.Rds") @@ -507,7 +510,7 @@ libstargets.df$nearestpixl<-as.factor(libstargets.df$nearestpixl) levels(libstargets.df$nearestpixl)<-(c("Bellegrade","Dourbes","Quartier","Alfalfa","ThorntonGap","BerryHollow","Novarupta","UganikIsland")) ``` -Below is another initializer for the PIXL abrasion data. This sets the variables for each PIXL abrasion. +Below is another initializer for the PIXL abrasion data. This sets the variables for each PIXL abrasion name. ```{r} #Sets each nearest PIXL variable for future use in deciding which target is closest to a LIBS sample Bellegrade<-libstargets.df[libstargets.df$nearestpixl=="Bellegrade",]$target @@ -520,7 +523,7 @@ Novarupta<-libstargets.df[libstargets.df$nearestpixl=="Novarupta",]$target UganikIsland<-libstargets.df[libstargets.df$nearestpixl=="UganikIsland",]$target ``` -Next, we filter out the LIBS targets that are not within the specified distance variable. Then, we merge the LIBS data with the respective PIXL abrasion by mutating and adding an abrasion column that has the abrasion name closest to each LIBS target. We also add a column, LIBS or PIXL, which denotes if the row of data is from the PIXL and LIBS data sets. We also set up the libs.tern matrix which will +Next, we filter out the LIBS targets that are not within the specified distance variable. Then, we merge the LIBS data with the respective PIXL abrasion by mutating and adding an abrasion column that has the abrasion name closest to each LIBS target. We also add a column, LIBS or PIXL, which denotes if the row of data is from the PIXL and LIBS data sets. We also set up the libs.tern matrix which will format the data properly for the ternary plot. This groups the cation compositions given by Dr. Rogers to set up the ternary diagram axes. ```{r} included.libs<-(libstargets.df%>% filter(Distance% mutate(Abrasion = ifelse(target%in%Alfalfa,"Alfalfa", - ifelse(target %in% Bellegrade, "Belegrade", + ifelse(target %in% Bellegrade, "Bellegrade", ifelse(target %in% BerryHollow, "BerryHollow", ifelse(target %in% Dourbes, "Dourbes", ifelse(target %in% Novarupta, "Novarupta", @@ -574,15 +577,11 @@ c("2","3","4,6,7","5,8,9","","","","", ## 5.2 Contribution -This work was also a combination of me and Margo. The data set creation was both of us in our brainstorming as this utilizes the data set we created of latitude and longitude for PIXL. -- Add more here -- Very similar to other two sections add in later, Margo and I worked on most of this together +This work was also a combination of Margo and I. The data set creation was both of us in our brainstorming as this utilizes the data set we created of latitude and longitude for PIXL. The setting up of this plot was also collaborative between Margo and myself, we worked together to debug and set up how to best format the data for this ternary plot. ## 5.3 Methods Description -- Started with filtering original data to get rid of SCCT values -- then set up ternary data frame by mutating by cation compositions -- then mutated to make the PIXL abrasions the key, so the LIBS targets are colored by the closest PIXL abrasion, creating a form of clusters. +For this ternary representation, we took the time to remove the SCCT (earth reference data) from the LIBS data, remove the atmospheric sample from the PIXL data, use a distance function to match PIXL abrasions to corresponding LIBS targets within 7 meters of the respective abrasion (or whatever the specified distance) and set up a ternary data frame with cation combinations. Then, the data frame is mutated to make the PIXL abrasions as the key (color LIBS targets by related PIXL abrasion) and plotted on the ternary diagram. We also plot the PIXL samples sorted by igneous or sedimentary as stated by the PIXL data set. This can help show the mineral evolution from igneous to sedimentary and which PIXL abrasions correlate to this. ## 5.4 Result and Discussion Using all of the manipulation done for the creation of the ternary plot, we then plot using the ggtern command. We will color by abrasion to see the distribution of composition between different abrasions. This should help us be able to draw different conclusions about how abrasions relate or don't relate. The max distance between the PIXL target and LIBS sample can be modified however desired. @@ -610,18 +609,342 @@ ggtern(libs.tern, ggtern::aes(x=x,y=y,z=z)) + size=2.7)) ``` + ## 5.5 Conclusions and Future Work -Based on this ternary plot, we can see Alfalfa and Belegrade are higher in Si+Al and Uganik Island is an outlier. As this was the last piece of the PIXL data in the data set and it was missing a pair since every other abrasion was made up of two samples, it is included in here but until the data set is updated there is not enough context to explain why it is so vastly different. I would assume it is due to how the robot is traveling and the location of the UganikIsland abrasion is very different than the other 7 abrasions. -- Future work, would include more data to gain broader context +Based on this ternary plot, we can see Alfalfa and Bellegrade are higher in Si+Al and Uganik Island is an outlier. We can also see the rock evolution from igneous (black circles) to sedimentary (black triangles) as we move from higher Si+Al (over 80 %) to low in Si+Al and high in Fe+Mg. This conclusion was commented on by Andrew Steele of the Carnegie Institute of Science. As this was the last piece of the PIXL data in the data set and it was missing a pair since every other abrasion was made up of two samples, it is included in here but until the data set is updated there is not enough context to explain why it is so vastly different. I would assume it is due to how the robot is traveling and the location of the Uganik Island abrasion is very different than the other 7 abrasions. Future work could include diving deeper into the evolution process of rocks (igneous abrasions Alfalfa and Dourbes to sedimentary abrasions Thornton Gap). # Bibliography -Provide a listing of references and other sources. -* Analyst's Notebook -* Not sure what else is relevant, most of what I used was similar to Analyst's Notebook +* “Mars Rock Samples - NASA Science.” NASA, science.nasa.gov/mission/mars-2020- +perseverance/mars-rock-samples/. +* “Analyst Notebook”, https://an.rsl.wustl.edu/m20/AN/account/login.aspx. # Appendix -*Include here whatever you think is relevant to support the main content of your notebook. For example, you may have only include example figures above in your main text but include additional ones here. Or you may have done a more extensive investigation, and want to put more results here to document your work in the semester. Be sure to divide appendix into appropriate sections and make the contents clear to the reader using approaches discussed above. * -Should I add more examples here of soil composition plots of different abrasions? I also could add heat map analysis to this notebook as a finding but wasn't sure if it was really relevant. +Here, I will display some of the earlier soil composition plots for different PIXL abrasions. + +```{r, include=FALSE} +#Earth quartiles +earthquartiles.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/Data/LIBS_training_set_quartiles.Rds") +#Load in LIBS data +libs.df <- readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/Data/supercam_libs_moc_loc.Rds") +#Drop the standard deviation features, the sum of the percentages, +#the distance, and the total frequencies +libs.df <- libs.df %>% + select(!(c(distance_mm,Tot.Em.,SiO2_stdev,TiO2_stdev,Al2O3_stdev,FeOT_stdev, + MgO_stdev,Na2O_stdev,CaO_stdev,K2O_stdev,Total))) +# Convert the points to numeric +libs.df$point <- as.numeric(libs.df$point) +libs.df[,6:13] <- sapply(libs.df[,6:13],as.numeric) +#remove the scct/reference samples +libs.df<-libs.df%>% + filter(!(grepl("scct", target))) +#add a column to indicate the nearest pixl +libs.df<-cbind(nearestpixl=0,libs.df) +#make a dataframe of just the LIBS Lat/Long and target name and remove duplicates +libstargets.df<-libs.df[,c(1,3,4,5)] +libstargets.df<-distinct(libstargets.df) +``` + +```{r, include=FALSE} +#Choose max distance variable between PIXL and LIBS data +meters = 7 +#Choose PIXL abrasion you want to look at +abrasion_name = "Alfalfa" +``` + +```{r, include=FALSE} +#read in pixl data with lat/long +pixl.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/StudentData/pixl_sol_coordinates.Rds") +#include only pixl metadata +pixl.df<-pixl.df %>% + select(c(1,2,19,20,22)) +#convert Lat/Long to numeric +pixl.df$Lat <- as.numeric(pixl.df$Lat) +pixl.df$Long <- as.numeric(pixl.df$Long) +#remove rows so we only have one sample per abrasion and remove atmospheric sample +pixl.df<-pixl.df[c(2,4,6,8,10,12,14,16),] +``` + +```{r, include=FALSE} +libstargets.df<-cbind(libstargets.df,"Distance"=0,"Bellegrade"=0,"Dourbes"=0,"Quartier"=0,"Alfalfa"=0,"ThorntonGap"=0,"Berry Hollow"=0,"Novarupta"=0,"Uganik Island"=0) +``` + +```{r, include=FALSE} +for(i in 1:nrow(libstargets.df)) { + libstargets.df[i,c(6:13)]<-c(distHaversine(pixl.df[1,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[2,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[3,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[4,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[5,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[6,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[7,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[8,c(1,2)],libstargets.df[i,c(2,3)],r=3393169)) + + libstargets.df[i,1]<-which.min(libstargets.df[i,c(6:13)]) + libstargets.df[i,5]<-min(libstargets.df[i,c(6:13)]) +} +libstargets.df$nearestpixl<-as.factor(libstargets.df$nearestpixl) +levels(libstargets.df$nearestpixl)<-(c("Bellegrade","Dourbes","Quartier","Alfalfa","ThorntonGap","Berry Hollow","Novarupta","Uganik Island")) +``` + +```{r, include=FALSE} +Bellegrade<-libstargets.df[libstargets.df$nearestpixl=="Bellegrade",]$target +Dourbes<-libstargets.df[libstargets.df$nearestpixl=="Dourbes",]$target +Quartier<-libstargets.df[libstargets.df$nearestpixl=="Quartier",]$target +Alfalfa<-libstargets.df[libstargets.df$nearestpixl=="Alfalfa",]$target +ThorntonGap<-libstargets.df[libstargets.df$nearestpixl=="ThorntonGap",]$target +BerryHollow<-libstargets.df[libstargets.df$nearestpixl=="Berry Hollow",]$target +Novarupta<-libstargets.df[libstargets.df$nearestpixl=="Novarupta",]$target +UganikIsland<-libstargets.df[libstargets.df$nearestpixl=="Uganik Island",]$target +``` + +```{r, include=FALSE} +included.libs<-(libstargets.df%>% + filter(Distance% + filter(target %in% included.libs) +libs.matrix <- libs.matrix[,c(5,7:14)] +libs.matrix<-libs.matrix[,c(1:2,4:9,3)] +libs.matrix<-cbind("Abrasion"=0,libs.matrix) +libs.matrix<-libs.matrix%>% + mutate(Abrasion = ifelse(target%in%Alfalfa,"Alfalfa", + ifelse(target %in% Bellegrade, "Bellegrade", + ifelse(target %in% BerryHollow, "Berry Hollow", + ifelse(target %in% Dourbes, "Dourbes", + ifelse(target %in% Novarupta, "Novarupta", + ifelse(target %in% Quartier, "Quartier", + ifelse(target %in% ThorntonGap, "ThorntonGap", + ifelse(target %in% UganikIsland, "Uganik Island",Abrasion))))))))) +libs.matrix<-cbind(libsorpixl=1,libs.matrix) +``` + +```{r, include=FALSE} +#read in pixl data with lat/long +pixl.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/StudentData/pixl_sol_coordinates.Rds") +pixl.df<-pixl.df %>% + select(c(5:8,12:14,17,19,18,22)) +#reorder pixl columns so that it matches libs data organization +pixl.df<-pixl.df[,c(11,10,4,3,8,2,6,1,5,7)] +#remove atmospheric sample +pixl.df<-pixl.df[2:16,] +pixl.df<-cbind(libsorpixl=0,pixl.df) +``` + +```{r, include=FALSE} +colnames(pixl.df)<-colnames(libs.matrix) +pixllibs.df<-rbind(pixl.df,libs.matrix) +``` + +```{r, include=FALSE} +# Earth quartiles +filtered_rows <- earthquartiles.df %>% + filter(`Training set Quartiles` %in% c("1st", "3rd", "Med")) +earthquartiles_long <- filtered_rows %>% + pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage") + +earthquartiles_long <- earthquartiles_long %>% rename(Quartiles = `Training set Quartiles`) +``` +```{r, include=FALSE} +# Filter for the specific abrasion sample, e.g., "Alfalfa" +pixllibs_filtered <- pixllibs.df %>% + filter(Abrasion == abrasion_name) + +# Pivot the data to longer format for ggplot +pixllibs_long <- pixllibs_filtered %>% + pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage") + +desired_order <- c("SiO2", "Al2O3", "FeOT", "MgO", "CaO", "Na2O", "K2O", "TiO2") # Specify your custom order here +pixllibs_long$Compound <- factor(pixllibs_long$Compound, levels = desired_order) +``` + +```{r, include=TRUE} +# Map the PIXL/LIBS column to color and use target_name to differentiate lines +suppressWarnings(ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) + + geom_line() + + geom_point() + + scale_y_continuous(trans='log10') + + # Add Earth quartile lines using earthquartiles_long + geom_line(data = earthquartiles_long, aes(x = Compound, y = Percentage, linetype = Quartiles, group = Quartiles), + color = "black", linetype = "dotted") + + labs(title = paste("Soil Composition for PIXL",abrasion_name,"and LIBS within", meters, "meters", sep = " "), + x = "Chemical Compound", + y = "Weight Percentage", + color = "Measurement Type", + linetype = "Quartiles", + caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") + + scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) + + annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) + + annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) + + annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)+ + theme_minimal()+ + # Center the caption on the left side + theme( + plot.caption = element_text(hjust = 0) # Aligns caption to the left + )) + +``` + +```{r, include=FALSE} +#Earth quartiles +earthquartiles.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/Data/LIBS_training_set_quartiles.Rds") +#Load in LIBS data +libs.df <- readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/Data/supercam_libs_moc_loc.Rds") +#Drop the standard deviation features, the sum of the percentages, +#the distance, and the total frequencies +libs.df <- libs.df %>% + select(!(c(distance_mm,Tot.Em.,SiO2_stdev,TiO2_stdev,Al2O3_stdev,FeOT_stdev, + MgO_stdev,Na2O_stdev,CaO_stdev,K2O_stdev,Total))) +# Convert the points to numeric +libs.df$point <- as.numeric(libs.df$point) +libs.df[,6:13] <- sapply(libs.df[,6:13],as.numeric) +#remove the scct/reference samples +libs.df<-libs.df%>% + filter(!(grepl("scct", target))) +#add a column to indicate the nearest pixl +libs.df<-cbind(nearestpixl=0,libs.df) +#make a dataframe of just the LIBS Lat/Long and target name and remove duplicates +libstargets.df<-libs.df[,c(1,3,4,5)] +libstargets.df<-distinct(libstargets.df) +``` + +```{r, include=FALSE} +#Choose max distance variable between PIXL and LIBS data +meters = 7 +#Choose PIXL abrasion you want to look at +abrasion_name = "Quartier" +``` + +```{r, include=FALSE} +#read in pixl data with lat/long +pixl.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/StudentData/pixl_sol_coordinates.Rds") +#include only pixl metadata +pixl.df<-pixl.df %>% + select(c(1,2,19,20,22)) +#convert Lat/Long to numeric +pixl.df$Lat <- as.numeric(pixl.df$Lat) +pixl.df$Long <- as.numeric(pixl.df$Long) +#remove rows so we only have one sample per abrasion and remove atmospheric sample +pixl.df<-pixl.df[c(2,4,6,8,10,12,14,16),] +``` + +```{r, include=FALSE} +libstargets.df<-cbind(libstargets.df,"Distance"=0,"Bellegrade"=0,"Dourbes"=0,"Quartier"=0,"Alfalfa"=0,"ThorntonGap"=0,"Berry Hollow"=0,"Novarupta"=0,"Uganik Island"=0) +``` + +```{r, include=FALSE} +for(i in 1:nrow(libstargets.df)) { + libstargets.df[i,c(6:13)]<-c(distHaversine(pixl.df[1,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[2,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[3,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[4,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[5,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[6,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[7,c(1,2)],libstargets.df[i,c(2,3)],r=3393169), + distHaversine(pixl.df[8,c(1,2)],libstargets.df[i,c(2,3)],r=3393169)) + + libstargets.df[i,1]<-which.min(libstargets.df[i,c(6:13)]) + libstargets.df[i,5]<-min(libstargets.df[i,c(6:13)]) +} +libstargets.df$nearestpixl<-as.factor(libstargets.df$nearestpixl) +levels(libstargets.df$nearestpixl)<-(c("Bellegrade","Dourbes","Quartier","Alfalfa","ThorntonGap","Berry Hollow","Novarupta","Uganik Island")) +``` + +```{r, include=FALSE} +Bellegrade<-libstargets.df[libstargets.df$nearestpixl=="Bellegrade",]$target +Dourbes<-libstargets.df[libstargets.df$nearestpixl=="Dourbes",]$target +Quartier<-libstargets.df[libstargets.df$nearestpixl=="Quartier",]$target +Alfalfa<-libstargets.df[libstargets.df$nearestpixl=="Alfalfa",]$target +ThorntonGap<-libstargets.df[libstargets.df$nearestpixl=="ThorntonGap",]$target +BerryHollow<-libstargets.df[libstargets.df$nearestpixl=="Berry Hollow",]$target +Novarupta<-libstargets.df[libstargets.df$nearestpixl=="Novarupta",]$target +UganikIsland<-libstargets.df[libstargets.df$nearestpixl=="Uganik Island",]$target +``` + +```{r, include=FALSE} +included.libs<-(libstargets.df%>% + filter(Distance% + filter(target %in% included.libs) +libs.matrix <- libs.matrix[,c(5,7:14)] +libs.matrix<-libs.matrix[,c(1:2,4:9,3)] +libs.matrix<-cbind("Abrasion"=0,libs.matrix) +libs.matrix<-libs.matrix%>% + mutate(Abrasion = ifelse(target%in%Alfalfa,"Alfalfa", + ifelse(target %in% Bellegrade, "Bellegrade", + ifelse(target %in% BerryHollow, "Berry Hollow", + ifelse(target %in% Dourbes, "Dourbes", + ifelse(target %in% Novarupta, "Novarupta", + ifelse(target %in% Quartier, "Quartier", + ifelse(target %in% ThorntonGap, "ThorntonGap", + ifelse(target %in% UganikIsland, "Uganik Island",Abrasion))))))))) +libs.matrix<-cbind(libsorpixl=1,libs.matrix) +``` + +```{r, include=FALSE} +#read in pixl data with lat/long +pixl.df<-readRDS("/academics/MATP-4910-F24/DAR-Mars-F24/StudentData/pixl_sol_coordinates.Rds") +pixl.df<-pixl.df %>% + select(c(5:8,12:14,17,19,18,22)) +#reorder pixl columns so that it matches libs data organization +pixl.df<-pixl.df[,c(11,10,4,3,8,2,6,1,5,7)] +#remove atmospheric sample +pixl.df<-pixl.df[2:16,] +pixl.df<-cbind(libsorpixl=0,pixl.df) +``` + +```{r, include=FALSE} +colnames(pixl.df)<-colnames(libs.matrix) +pixllibs.df<-rbind(pixl.df,libs.matrix) +``` + +```{r, include=FALSE} +# Earth quartiles +filtered_rows <- earthquartiles.df %>% + filter(`Training set Quartiles` %in% c("1st", "3rd", "Med")) +earthquartiles_long <- filtered_rows %>% + pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage") + +earthquartiles_long <- earthquartiles_long %>% rename(Quartiles = `Training set Quartiles`) +``` + +```{r, include=FALSE} +# Filter for the specific abrasion sample, e.g., "Alfalfa" +pixllibs_filtered <- pixllibs.df %>% + filter(Abrasion == abrasion_name) + +# Pivot the data to longer format for ggplot +pixllibs_long <- pixllibs_filtered %>% + pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage") + +desired_order <- c("SiO2", "Al2O3", "FeOT", "MgO", "CaO", "Na2O", "K2O", "TiO2") # Specify your custom order here +pixllibs_long$Compound <- factor(pixllibs_long$Compound, levels = desired_order) +``` + +```{r, include=TRUE} +# Map the PIXL/LIBS column to color and use target_name to differentiate lines +suppressWarnings(ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) + + geom_line() + + geom_point() + + scale_y_continuous(trans='log10') + + # Add Earth quartile lines using earthquartiles_long + geom_line(data = earthquartiles_long, aes(x = Compound, y = Percentage, linetype = Quartiles, group = Quartiles), + color = "black", linetype = "dotted") + + labs(title = paste("Soil Composition for PIXL",abrasion_name,"and LIBS within", meters, "meters", sep = " "), + x = "Chemical Compound", + y = "Weight Percentage", + color = "Measurement Type", + linetype = "Quartiles", + caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") + + scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) + + annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) + + annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) + + annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)+ + theme_minimal()+ + # Center the caption on the left side + theme( + plot.caption = element_text(hjust = 0) # Aligns caption to the left + )) + +``` diff --git a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.nb.html b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.nb.html index 3b7e802..b46da0e 100644 --- a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.nb.html +++ b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.nb.html @@ -1768,13 +1768,6 @@

DAR Project and Group Members

0.0 Preliminaries.

-

This report is generated from an R Markdown file that includes all -the R code necessary to produce the results described and embedded in -the report. Code blocks can be suppressed from output for readability -using the command code {R, echo=show} in the code block -header. If show <- FALSE the code block will be -suppressed; if show <- TRUE then the code will be -show.

@@ -1790,7 +1783,6 @@

0.0 Preliminaries.

<!-- rnb-text-begin --> -<!-- Expand this list as necessary for your notebook --> Executing this R notebook requires some subset of the following packages: * `ggplot2` @@ -1805,6 +1797,7 @@

0.0 Preliminaries.

* `caret` * `ggrepel` * `ggtern` +* `geosphere` These will be installed and loaded as necessary (code suppressed). @@ -1834,28 +1827,25 @@

0.0 Preliminaries.

* Section 6.0 Overall conclusions and suggestions -* Section 7.0 Appendix This section describe the following additional works that may be helpful in the future work: *list subjects*. +* Section 7.0 Appendix This section describe the following additional works that may be helpful in the future work: Additional Soil Composition Plots of LIBS and PIXL # 3.0 Finding 1: PIXL and LIBS Matching -_Give a highlevel overview of the major finding. What questions were your trying to address, what approaches did you employ, and what happened?_ - Firstly, we will be taking a look at how PIXL and LIBS correspond. Our group found very early in our research that there wasn't a feature among them that can be used to match the data sets. For example, the columns of PIXL are organized by latitude and longitude as well as sample number (1-16), sample name, and abrasion name. Unfortunately, LIBS wasn't sorted the same way. LIBS was organized by the sol that the sample was taken at. LIBS is broken up into many different types of samples as well, including the fact it carries around earth reference data to be used in comparing with different sample sites. That being said, in order to match PIXL targets to corresponding LIBS samples, Margo and I created a new data set that added another metadata feature to PIXL (latitude and longitude coordinates) which we obtained from the Analyst's Notebook. Once this was added in, we realized that the longitude and latitude didn't really match. So Margo created a distance function to match LIBS samples to PIXL targets based on whatever distance a person specifies. Originally, we set it to be rounded to three thousandths and match based on that. This helped answer the question of how can we correlate the LIBS and PIXL data sets to be able to plot them on the same axis of whatever plot is trying to be created. I was curious to see how close PIXL targets were to LIBS sample sites as well as how many LIBS samples would be associated with a PIXL target perhaps with a radius of 7 or 10 meters. ## 3.1 Data, Code, and Resources -Here is a list data sets, codes, that are used in your work. Along with brief description and URL where they are located. +1. peterc_finalProjectF24.Rmd (with knit pdf and html) is this notebook. +[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) -1. peterc-finalProjectF24.Rmd (with knit pdf and html) is this notebook. -[https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd) 2. v1_libs_to_sample.Rds is the combined data set of PIXL and LIBS that includes the distance from a PIXL abrasion to a LIBS sample. [https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentData/v1_libs_to_sample.Rds](https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentData/v1_libs_to_sample.Rds). -Firstly, we set the number of meters distance threshold between a PIXL abrasion and LIBS sample. Within the v1_libs_to_sample.Rds, which Margo and I collaborated on there is a distance variable that is set via a function that Margo created to measure the distance between a PIXL abrasion and LIBS sample using their latitude and longitude coordinates. +Firstly, we set the number of meters distance threshold between a PIXL abrasion and LIBS sample. Within the v1_libs_to_sample.Rds, which Margo and I collaborated on there is a distance variable that is set via a function that Margo created to measure the distance between a PIXL abrasion and LIBS sample using their latitude and longitude coordinates. 7 meters is the best metric because that is the maximum distance the LIBS instrument can accurately collect data from. <!-- rnb-text-end --> @@ -1990,26 +1980,28 @@

3.5 Conclusions, Limitations, and Future Work.

4.0 Finding 2: Soil Composition Analysis

-

Give a highlevel overview of the major finding. What questions -were your trying to address, what approaches did you employ, and what -happened?

Using the LIBS and PIXL combined data set, I created a plot of the composition percentages of chemical compounds such as Si02, K20, etc. using log scaling to compare the compositions of a PIXL abrasion and the corresponding LIBS sample compositions (based on the LIBS samples for x distance away from a PIXL abrasion). The question I was trying to answer was how does the LIBS data of a certain area compare to the PIXL data of -that area? By looking at the composition of the soil in certain -locations, we can compare the differences in the PIXL abrasion and -relating LIBS samples for a certain area utilizing the same data set -(v1_libs_to_sample.Rmd). In order to accomplish this,

+that area? Are there many differences between locations (meaning which +abrasions and their corresponding LIBS targets are different and in what +ways, do igneous vs. sedimentary show a pattern?). In order to +accomplish this, we will use a distance function to filter within 7 +meters of distance between a PIXL sample and LIBS target (this is the +maximum distance of accuracy based on NASA’s information on LIBS +spectroscopy machinery). Then, the data for earth quartile references +(first and third quartiles and median), PIXL abrasion chemical +composition, and corresponding LIBS target chemical compositions will be +plotted based on the chosen PIXL abrasion (only one abrasion is plotted +at a time).

4.1 Data, Code, and Resources

-

Here is a list data sets, codes, that are used in your work. Along -with brief description and URL where they are located.

  1. peterc_finalProjectF24.Rmd (with knit pdf and html) is this -notebook. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd

  2. +notebook. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd

  3. peterc_assignment5.Rmd (with knit pdf and html) which is my previous notebook. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/tree/main/StudentNotebooks/Assignment05/peterc_assignment05.Rmd

  4. supercam_libs_moc_loc.Rds which is the original LIBS data given @@ -2023,7 +2015,7 @@

    4.1 Data, Code, and Resources

    drop the standard deviation columns and sum of percentage columns leaving us with just the weighted composition in terms of numerical data. We also remove the scct values, as those values are the ones that -are earth reference samples that Perserverance carries with it. +are earth reference samples that Perseverance carries with it. Therefore, they will not be very relevant when plotting the LIBS data as we are focused on the Mars soil compositions.

    @@ -2055,11 +2047,11 @@

    4.1 Data, Code, and Resources

    Set meters and chosen abrasion to act as a slider in the 2d app.

    - +
    #Choose max distance variable between PIXL and LIBS data
     meters = 7
     #Choose PIXL abrasion you want to look at
    -abrasion_name = "Alfalfa"
    +abrasion_name = "ThorntonGap" @@ -2177,7 +2169,7 @@

    4.1 Data, Code, and Resources

    composition line plot.

    - +
    included.libs<-(libstargets.df%>%
       filter(Distance<meters))$target
     libs.matrix <-libs.df %>%
    @@ -2187,7 +2179,7 @@ 

    4.1 Data, Code, and Resources

    libs.matrix<-cbind("Abrasion"=0,libs.matrix) libs.matrix<-libs.matrix%>% mutate(Abrasion = ifelse(target%in%Alfalfa,"Alfalfa", - ifelse(target %in% Bellegrade, "Belegrade", + ifelse(target %in% Bellegrade, "Bellegrade", ifelse(target %in% BerryHollow, "Berry Hollow", ifelse(target %in% Dourbes, "Dourbes", ifelse(target %in% Novarupta, "Novarupta", @@ -2203,8 +2195,17 @@

    4.1 Data, Code, and Resources

    4.2 Contribution

    Some of the data manipulating work was Margo’s, such as the distance function. In terms of pivoting the data frame and the other steps of the -preprocessing is my own work. The manipulating below to plot the line -soil composition plots is my own.

    +preprocessing is my own work. The manipulating and setup of data below +to plot the line soil composition plots is my own. Margo and I worked +together to create the data sets used. In our presentation, David was +able to create a facid grid to compliment my single abrasion analysis +which showed the average LIBS target chemical composition and +corresponding PIXL abrasion composition. This was done in RShiny and +implemented in the app, so I felt that redoing the same plot wouldn’t be +necessary. I focused on plotting one specific abrasion to provide more +in depth analysis of one abrasion and the surrounding area since David +was able to provide more context and plot the PIXL abrasions all at +once.

4.3 Methods Description

@@ -2218,8 +2219,8 @@

4.3 Methods Description

composition values. We also need an indicator of if the data is from PIXL or LIBS, which also is helpful for building the line plots.

Users will have to set the distance variable in order to choose the -max distance between PIXL abrasions and LIBS targets. This can vastly -change the number of lines on the plots which can help prevent +maximum distance between PIXL abrasions and LIBS targets. This can +vastly change the number of lines on the plots which can help prevent overcrowded plots. Users also can set a variable to choose a specific PIXL abrasion and corresponding LIBS targets, which is easier to interpret as plotting all of the LIBS and PIXL composition information @@ -2228,7 +2229,8 @@

4.3 Methods Description

4.4 Result and Discussion

First, we will turn the earth quartile information into a long data -frame (meaning pivoting the columns into the values).

+frame (meaning pivoting the columns into the values) and only select the +first and third quartile rows.

@@ -2259,27 +2261,35 @@

4.4 Result and Discussion

For the plot, we use ggplot to plot the pixllibs_long data frame we created. The plot is colored by if the line is a PIXL abrasion’s composition or a LIBS target’s composition. We also add a layer with the -earth quartile information, which is the dotted lines.

+earth quartile information, which is the dotted lines. The weight +percentages on the y axis are log scaled as it makes the plot more +readable, but this can be edited (will be added as a toggle in the +app).

- +
# Earth quartiles
-earthquartiles_long <- earthquartiles.df %>%
+filtered_rows <- earthquartiles.df %>%
+  filter(`Training set Quartiles` %in% c("1st", "3rd", "Med"))
+earthquartiles_long <- filtered_rows %>%
   pivot_longer(cols = starts_with("SiO2"):last_col(), names_to = "Compound", values_to = "Percentage")
 
 earthquartiles_long <- earthquartiles_long %>% rename(Quartiles = `Training set Quartiles`)
-

I still plan to update and try using the ggplotlay feature to -incorporate all the abrasions and data onto one grid of line plots. I -also am going to add plots where the mean is taken of all the LIBS -targets that correspond to a PIXL abrasion so the plot will only have -one LIBS line and one PIXL line (along with the references), this is all -just for the draft. I also need to only add certain quartile information -and label them, this is just a placeholder of the previous plot. Also -maybe will add in SCCT values as references, not sure if they are super -relevant or how to sort them.

+

To save space in this notebook, I did not plot each abrasion (based +on chosen abrasion variable name). In comparing each PIXL abrasion and +the corresponding LIBS targets, I found that the PIXL abrasions +corresponding to igneous had very similar plots, while the PIXL +abrasions corresponding to sedimentary had very similar plots. The +igneous/sedimentary indicator is shown in the PIXL data. An interesting +thing to note is that for some abrasions, like Alfalfa and ThorntonGap, +the chemical compositions of both PIXL samples in the abrasion are the +same. For other abrasions, like Bellegrade, the chemical compositions of +the PIXL samples in the Bellegrade abrasion differ. Also, many of the +plots had a few points with very low K2O which seems like a major +outlier.

4.5 Conclusions and Future Work

@@ -2288,7 +2298,12 @@

4.5 Conclusions and Future Work

For example, oxide presence doesn’t necessarily indicate life, but it could indicate biological or chemical life processes. For example, CaO can indicate the presence of old biological material like shells or -fossils. -Add more about future work, not sure what else to include

+fossils. For future work, I would like to see why certain abrasions +differ in their PIXL core sample composition. Is this based on the +research done by scientists in selecting specific abrasions and trying +to obtain differing samples for abrasions in certain areas? Or is this +by chance? Or is it simply showing more rock variety or weathering the +certain abrasions?

@@ -2297,17 +2312,26 @@

5.0 Finding 3: Analyzing Cation Combinations using LIBS and PIXL

Using the LIBS and PIXL combined data set, we created a ternary plot to show the distribution of LIBS samples sorted by what PIXL abrasion they are closest to (based on a chosen distance variable). Much of the -data preprocessing is similar to Finding 1 which we will repeat here. -However, the goal here is to analyze how different groups of LIBS -samples (colored by matching PIXL abrasion) differ by cation -composition.

+data preprocessing is similar to Finding 1 which we will repeat here. It +will involve using a distance function to correlate LIBS targets with +PIXL samples, matching the data based on the closest PIXL sample, and +plotting the LIBS data (colored by corresponding PIXL abrasion) and the +PIXL abrasions on a ternary plot. The goal here is to analyze how +different groups of LIBS samples (colored by matching PIXL abrasion) +differ by cation composition. Do igneous vs. sedimentary rock play a +roll in composition tendencies and show a pattern? By looking at the +composition of the soil in certain locations, we can compare the +differences in the PIXL abrasion and relating LIBS samples for a certain +area by combining the LIBS and PIXL data sets. In order to accomplish +this, we will use a distance function to filter within 7 meters of +distance between a PIXL sample and LIBS target (this is the maximum +distance of accuracy based on NASA’s information on LIBS spectroscopy +machinery).

5.1 Data, Code, and Resources

-

Here is a list data sets, codes, that are used in your work. Along -with brief description and URL where they are located.

    -
  1. peterc-finalProjectF24.Rmd (with knit pdf and html) is this -notebook. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment07_DraftFinalProjectNotebook/peterc_finalProjectF24_roughdraft.Rmd

  2. +
  3. peterc_finalProjectF24.Rmd (with knit pdf and html) is this +notebook. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.Rmd

  4. supercam_libs_moc_loc.Rds which is the original LIBS data given to our research group. https://github.rpi.edu/DataINCITE/DAR-Mars-F24/blob/main/Data/supercam_libs_moc_loc.Rds

@@ -2340,7 +2364,7 @@

5.1 Data, Code, and Resources

weighted compositions.

- +
# Map the PIXL/LIBS column to color and use target_name to differentiate lines
 ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) +
   geom_line() +
@@ -2353,9 +2377,12 @@ 

5.1 Data, Code, and Resources

x = "Chemical Compound", y = "Weight Percentage", color = "Measurement Type", - linetype = "Earth Quartiles") + + linetype = "Quartiles", + caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") + scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) + - theme_minimal()
+ annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) + + annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) + + annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)
Warning in scale_y_continuous(trans = "log10") :
@@ -2363,12 +2390,323 @@ 

5.1 Data, Code, and Resources

Warning in scale_y_continuous(trans = "log10") : log-10 transformation introduced infinite values.
- -

+ +

+ +
  theme_minimal()+
+     # Center the caption on the left side
+  theme(
+    plot.caption = element_text(hjust = 0)  # Aligns caption to the left
+  )
+ + +
List of 196
+ $ line                            :List of 6
+  ..$ colour       : chr "black"
+  ..$ linewidth    : num 0.545
+  ..$ linetype     : num 1
+  ..$ lineend      : chr "butt"
+  ..$ arrow        : logi FALSE
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_line" "element"
+ $ rect                            :List of 5
+  ..$ fill         : chr "white"
+  ..$ colour       : chr "black"
+  ..$ linewidth    : num 0.545
+  ..$ linetype     : num 1
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_rect" "element"
+ $ text                            :List of 11
+  ..$ family       : chr ""
+  ..$ face         : chr "plain"
+  ..$ colour       : chr "black"
+  ..$ size         : num 12
+  ..$ hjust        : num 0.5
+  ..$ vjust        : num 0.5
+  ..$ angle        : num 0
+  ..$ lineheight   : num 0.9
+  ..$ margin       : 'margin' num [1:4] 0points 0points 0points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : logi FALSE
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ title                           : NULL
+ $ aspect.ratio                    : NULL
+ $ axis.title                      : NULL
+ $ axis.title.x                    :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 1
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 3points 0points 0points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.title.x.top                :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 0
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 0points 3points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.title.x.bottom             : NULL
+ $ axis.title.y                    :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 1
+  ..$ angle        : num 90
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 3points 0points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.title.y.left               : NULL
+ $ axis.title.y.right              :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 1
+  ..$ angle        : num -90
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 0points 0points 3points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text                       :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : chr "grey30"
+  ..$ size         : 'rel' num 0.8
+  ..$ hjust        : NULL
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : NULL
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text.x                     :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 1
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 2.4points 0points 0points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text.x.top                 :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : NULL
+  ..$ vjust        : num 0
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 0points 2.4points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text.x.bottom              : NULL
+ $ axis.text.y                     :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : num 1
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 2.4points 0points 0points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text.y.left                : NULL
+ $ axis.text.y.right               :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : num 0
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 0points 0points 2.4points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.text.theta                 : NULL
+ $ axis.text.r                     :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : num 0.5
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : 'margin' num [1:4] 0points 2.4points 0points 2.4points
+  .. ..- attr(*, "unit")= int 8
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ axis.ticks                      : list()
+  ..- attr(*, "class")= chr [1:2] "element_blank" "element"
+ $ axis.ticks.x                    : NULL
+ $ axis.ticks.x.top                : NULL
+ $ axis.ticks.x.bottom             : NULL
+ $ axis.ticks.y                    : NULL
+ $ axis.ticks.y.left               : NULL
+ $ axis.ticks.y.right              : NULL
+ $ axis.ticks.theta                : NULL
+ $ axis.ticks.r                    : NULL
+ $ axis.minor.ticks.x.top          : NULL
+ $ axis.minor.ticks.x.bottom       : NULL
+ $ axis.minor.ticks.y.left         : NULL
+ $ axis.minor.ticks.y.right        : NULL
+ $ axis.minor.ticks.theta          : NULL
+ $ axis.minor.ticks.r              : NULL
+ $ axis.ticks.length               : 'simpleUnit' num 3points
+  ..- attr(*, "unit")= int 8
+ $ axis.ticks.length.x             : NULL
+ $ axis.ticks.length.x.top         : NULL
+ $ axis.ticks.length.x.bottom      : NULL
+ $ axis.ticks.length.y             : NULL
+ $ axis.ticks.length.y.left        : NULL
+ $ axis.ticks.length.y.right       : NULL
+ $ axis.ticks.length.theta         : NULL
+ $ axis.ticks.length.r             : NULL
+ $ axis.minor.ticks.length         : 'rel' num 0.75
+ $ axis.minor.ticks.length.x       : NULL
+ $ axis.minor.ticks.length.x.top   : NULL
+ $ axis.minor.ticks.length.x.bottom: NULL
+ $ axis.minor.ticks.length.y       : NULL
+ $ axis.minor.ticks.length.y.left  : NULL
+ $ axis.minor.ticks.length.y.right : NULL
+ $ axis.minor.ticks.length.theta   : NULL
+ $ axis.minor.ticks.length.r       : NULL
+ $ axis.line                       : list()
+  ..- attr(*, "class")= chr [1:2] "element_blank" "element"
+ $ axis.line.x                     : NULL
+ $ axis.line.x.top                 : NULL
+ $ axis.line.x.bottom              : NULL
+ $ axis.line.y                     : NULL
+ $ axis.line.y.left                : NULL
+ $ axis.line.y.right               : NULL
+ $ axis.line.theta                 : NULL
+ $ axis.line.r                     : NULL
+ $ legend.background               : list()
+  ..- attr(*, "class")= chr [1:2] "element_blank" "element"
+ $ legend.margin                   : 'margin' num [1:4] 6points 6points 6points 6points
+  ..- attr(*, "unit")= int 8
+ $ legend.spacing                  : 'simpleUnit' num 12points
+  ..- attr(*, "unit")= int 8
+ $ legend.spacing.x                : NULL
+ $ legend.spacing.y                : NULL
+ $ legend.key                      : list()
+  ..- attr(*, "class")= chr [1:2] "element_blank" "element"
+ $ legend.key.size                 : 'simpleUnit' num 1.2lines
+  ..- attr(*, "unit")= int 3
+ $ legend.key.height               : NULL
+ $ legend.key.width                : NULL
+ $ legend.key.spacing              : 'simpleUnit' num 6points
+  ..- attr(*, "unit")= int 8
+ $ legend.key.spacing.x            : NULL
+ $ legend.key.spacing.y            : NULL
+ $ legend.frame                    : NULL
+ $ legend.ticks                    : NULL
+ $ legend.ticks.length             : 'rel' num 0.2
+ $ legend.axis.line                : NULL
+ $ legend.text                     :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : 'rel' num 0.8
+  ..$ hjust        : NULL
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : NULL
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ legend.text.position            : NULL
+ $ legend.title                    :List of 11
+  ..$ family       : NULL
+  ..$ face         : NULL
+  ..$ colour       : NULL
+  ..$ size         : NULL
+  ..$ hjust        : num 0
+  ..$ vjust        : NULL
+  ..$ angle        : NULL
+  ..$ lineheight   : NULL
+  ..$ margin       : NULL
+  ..$ debug        : NULL
+  ..$ inherit.blank: logi TRUE
+  ..- attr(*, "class")= chr [1:2] "element_text" "element"
+ $ legend.title.position           : NULL
+ $ legend.position                 : chr "right"
+ $ legend.position.inside          : NULL
+ $ legend.direction                : NULL
+ $ legend.byrow                    : NULL
+ $ legend.justification            : chr "center"
+ $ legend.justification.top        : NULL
+ $ legend.justification.bottom     : NULL
+ $ legend.justification.left       : NULL
+ $ legend.justification.right      : NULL
+ $ legend.justification.inside     : NULL
+ $ legend.location                 : NULL
+ $ legend.box                      : NULL
+ $ legend.box.just                 : NULL
+ $ legend.box.margin               : 'margin' num [1:4] 0cm 0cm 0cm 0cm
+  ..- attr(*, "unit")= int 1
+ $ legend.box.background           : list()
+  ..- attr(*, "class")= chr [1:2] "element_blank" "element"
+ $ legend.box.spacing              : 'simpleUnit' num 12points
+  ..- attr(*, "unit")= int 8
+  [list output truncated]
+ - attr(*, "class")= chr [1:2] "theme" "gg"
+ - attr(*, "complete")= logi TRUE
+ - attr(*, "validate")= logi TRUE
+ -

Load in PIXL data

+

Next, we will load in the PIXL data that is in StudentData as the +pixl_sol_coordinates data frame includes the latitude, longitude, and +sol of each PIXL sample. We only include the metadata as this is all +that is necessary for the distance function (the sample name and +coordinates of the sample) as well as only one PIXL sample from each +abrasion. As each abrasion has 2 PIXL samples taken, they have the same +latitude and longitude and therefore it is unnecessary to use both. We +also remove the atmospheric sample.

@@ -2425,7 +2763,7 @@

5.1 Data, Code, and Resources

Below is another initializer for the PIXL abrasion data. This sets -the variables for each PIXL abrasion.

+the variables for each PIXL abrasion name.

@@ -2439,7 +2777,9 @@

5.1 Data, Code, and Resources

respective PIXL abrasion by mutating and adding an abrasion column that has the abrasion name closest to each LIBS target. We also add a column, LIBS or PIXL, which denotes if the row of data is from the PIXL and LIBS -data sets. We also set up the libs.tern matrix which will

+data sets. We also set up the libs.tern matrix which will format the +data properly for the ternary plot. This groups the cation compositions +given by Dr. Rogers to set up the ternary diagram axes.

@@ -2484,22 +2824,26 @@

5.1 Data, Code, and Resources

5.2 Contribution

-

This work was also a combination of me and Margo. The data set +

This work was also a combination of Margo and I. The data set creation was both of us in our brainstorming as this utilizes the data -set we created of latitude and longitude for PIXL. - Add more here - -Very similar to other two sections add in later, Margo and I worked on -most of this together

+set we created of latitude and longitude for PIXL. The setting up of +this plot was also collaborative between Margo and myself, we worked +together to debug and set up how to best format the data for this +ternary plot.

5.3 Methods Description

-
    -
  • Started with filtering original data to get rid of SCCT values
  • -
  • then set up ternary data frame by mutating by cation -compositions
  • -
  • then mutated to make the PIXL abrasions the key, so the LIBS targets -are colored by the closest PIXL abrasion, creating a form of -clusters.
  • -
+

For this ternary representation, we took the time to remove the SCCT +(earth reference data) from the LIBS data, remove the atmospheric sample +from the PIXL data, use a distance function to match PIXL abrasions to +corresponding LIBS targets within 7 meters of the respective abrasion +(or whatever the specified distance) and set up a ternary data frame +with cation combinations. Then, the data frame is mutated to make the +PIXL abrasions as the key (color LIBS targets by related PIXL abrasion) +and plotted on the ternary diagram. We also plot the PIXL samples sorted +by igneous or sedimentary as stated by the PIXL data set. This can help +show the mineral evolution from igneous to sedimentary and which PIXL +abrasions correlate to this.

5.4 Result and Discussion

@@ -2566,42 +2910,141 @@

5.4 Result and Discussion

5.5 Conclusions and Future Work

-

Based on this ternary plot, we can see Alfalfa and Belegrade are -higher in Si+Al and Uganik Island is an outlier. As this was the last -piece of the PIXL data in the data set and it was missing a pair since -every other abrasion was made up of two samples, it is included in here -but until the data set is updated there is not enough context to explain -why it is so vastly different. I would assume it is due to how the robot -is traveling and the location of the UganikIsland abrasion is very -different than the other 7 abrasions. - Future work, would include more -data to gain broader context

+

Based on this ternary plot, we can see Alfalfa and Bellegrade are +higher in Si+Al and Uganik Island is an outlier. We can also see the +rock evolution from igneous (black circles) to sedimentary (black +triangles) as we move from higher Si+Al (over 80 %) to low in Si+Al and +high in Fe+Mg. This conclusion was commented on by Andrew Steele of the +Carnegie Institute of Science. As this was the last piece of the PIXL +data in the data set and it was missing a pair since every other +abrasion was made up of two samples, it is included in here but until +the data set is updated there is not enough context to explain why it is +so vastly different. I would assume it is due to how the robot is +traveling and the location of the Uganik Island abrasion is very +different than the other 7 abrasions. Future work could include diving +deeper into the evolution process of rocks (igneous abrasions Alfalfa +and Dourbes to sedimentary abrasions Thornton Gap).

Bibliography

-

Provide a listing of references and other sources.

    -
  • Analyst’s Notebook
  • -
  • Not sure what else is relevant, most of what I used was similar to -Analyst’s Notebook
  • +
  • “Mars Rock Samples - NASA Science.” NASA, +science.nasa.gov/mission/mars-2020- +perseverance/mars-rock-samples/.
  • +
  • “Analyst Notebook”, https://an.rsl.wustl.edu/m20/AN/account/login.aspx.

Appendix

-

Include here whatever you think is relevant to support the main -content of your notebook. For example, you may have only include example -figures above in your main text but include additional ones here. Or you -may have done a more extensive investigation, and want to put more -results here to document your work in the semester. Be sure to divide -appendix into appropriate sections and make the contents clear to the -reader using approaches discussed above. Should I add more -examples here of soil composition plots of different abrasions? I also -could add heat map analysis to this notebook as a finding but wasn’t -sure if it was really relevant.

+

Here, I will display some of the earlier soil composition plots for +different PIXL abrasions.

+ + + + + + + + + + + + + + + + + + + + + + + + +
# Map the PIXL/LIBS column to color and use target_name to differentiate lines
+suppressWarnings(ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) +
+  geom_line() +
+  geom_point() +
+  scale_y_continuous(trans='log10') +
+  # Add Earth quartile lines using earthquartiles_long
+  geom_line(data = earthquartiles_long, aes(x = Compound, y = Percentage, linetype = Quartiles, group = Quartiles), 
+            color = "black", linetype = "dotted") +
+  labs(title = paste("Soil Composition for PIXL",abrasion_name,"and LIBS within", meters, "meters", sep = " "),
+       x = "Chemical Compound",
+       y = "Weight Percentage",
+       color = "Measurement Type",
+       linetype = "Quartiles",
+       caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") +
+  scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) +
+  annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) +
+  annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) +
+  annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)+
+  theme_minimal()+
+     # Center the caption on the left side
+  theme(
+    plot.caption = element_text(hjust = 0)  # Aligns caption to the left
+  ))
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
# Map the PIXL/LIBS column to color and use target_name to differentiate lines
+suppressWarnings(ggplot(pixllibs_long, aes(x = Compound, y = Percentage, color = as.factor(libsorpixl), group = target)) +
+  geom_line() +
+  geom_point() +
+  scale_y_continuous(trans='log10') +
+  # Add Earth quartile lines using earthquartiles_long
+  geom_line(data = earthquartiles_long, aes(x = Compound, y = Percentage, linetype = Quartiles, group = Quartiles), 
+            color = "black", linetype = "dotted") +
+  labs(title = paste("Soil Composition for PIXL",abrasion_name,"and LIBS within", meters, "meters", sep = " "),
+       x = "Chemical Compound",
+       y = "Weight Percentage",
+       color = "Measurement Type",
+       linetype = "Quartiles",
+       caption = "The chemical composition of a PIXL abrasion and the corresponding LIBS targets \n within specified distance of respective abrasion.") +
+  scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("PIXL", "LIBS")) +
+  annotate("text", x = 5, y = .50, label = "1st Quartile", color = "black", hjust = 0) +
+  annotate("text", x = 5, y = 2, label = "Median", color = "black", hjust = 0) +
+  annotate("text", x = 5, y = 10, label = "3rd Quartile", color = "black", hjust = 0)+
+  theme_minimal()+
+     # Center the caption on the left side
+  theme(
+    plot.caption = element_text(hjust = 0)  # Aligns caption to the left
+  ))
+
+ +
-
LS0tCnRpdGxlOiAiRGF0YSBBbmFseXRpY3MgUmVzZWFyY2ggSW5kaXZpZHVhbCBGaW5hbCBQcm9qZWN0IFJlcG9ydCAtIE1hcnMiCmF1dGhvcjogIkNoYXJsb3R0ZSBQZXRlcnNvbiIKZGF0ZTogIkZhbGwgMjAyNCIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICczJwogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogdW5pdGVkCi0tLQoKCiMgREFSIFByb2plY3QgYW5kIEdyb3VwIE1lbWJlcnMKCiogUHJvamVjdCBuYW1lOiBNYXJzCiogR2l0SHViIElEOiBkYXItcGV0ZXJjCiogUHJvamVjdCB0ZWFtIG1lbWJlcnM6IERhbnRlIE13YXRpYm8sIERvw7FhIFJvYmVydHMsIERhdmlkIFdhbGN5emssIFh1YW50aW5nIFdhbmcsIEFzaHRvbiBDb21wdG9uLCBNYXJnbyBWYW5Fc3NlbHN0eW4sIE5pY29sYXMgTW9yYXdza2ksIENKIE1hcmlubywgQWFkaSBMYWhpcmkgCgojIDAuMCBQcmVsaW1pbmFyaWVzLgoKVGhpcyByZXBvcnQgaXMgZ2VuZXJhdGVkIGZyb20gYW4gUiBNYXJrZG93biBmaWxlIHRoYXQgaW5jbHVkZXMgYWxsIHRoZSBSIGNvZGUgbmVjZXNzYXJ5IHRvIHByb2R1Y2UgdGhlIHJlc3VsdHMgZGVzY3JpYmVkIGFuZCBlbWJlZGRlZCBpbiB0aGUgcmVwb3J0LiAgQ29kZSBibG9ja3MgY2FuIGJlIHN1cHByZXNzZWQgZnJvbSBvdXRwdXQgZm9yIHJlYWRhYmlsaXR5IHVzaW5nIHRoZSBjb21tYW5kIGNvZGUgYHtSLCAgZWNobz1zaG93fWAgaW4gdGhlIGNvZGUgYmxvY2sgaGVhZGVyLiBJZiBgc2hvdyA8LSBGQUxTRWAgdGhlIGNvZGUgYmxvY2sgd2lsbCBiZSBzdXBwcmVzc2VkOyBpZiBgc2hvdyA8LSBUUlVFYCB0aGVuIHRoZSBjb2RlIHdpbGwgYmUgc2hvdy4gCmBgYHtyfQojIFNldCB0byBUUlVFIHRvIGV4cGFuZCBSIGNvZGUgYmxvY2tzOyBzZXQgdG8gRkFMU0UgdG8gY29sbGFwc2UgUiBjb2RlIGJsb2NrcyAKc2hvdyA8LSBUUlVFCmBgYAoKPCEtLSBFeHBhbmQgdGhpcyBsaXN0IGFzIG5lY2Vzc2FyeSBmb3IgeW91ciBub3RlYm9vayAtLT4KRXhlY3V0aW5nIHRoaXMgUiBub3RlYm9vayByZXF1aXJlcyBzb21lIHN1YnNldCBvZiB0aGUgZm9sbG93aW5nIHBhY2thZ2VzOgoKKiBgZ2dwbG90MmAKKiBgdGlkeXZlcnNlYAoqIGBwYW5kb2NgCiogYHJtYXJrZG93bmAKKiBgc3RyaW5ncmAKKiBgZ2diaXBsb3RgCiogYGtuaXRyYAoqIGBycGFydGAKKiBgcnBhcnQucGxvdGAKKiBgY2FyZXRgCiogYGdncmVwZWxgCiogYGdndGVybmAKCgpUaGVzZSB3aWxsIGJlIGluc3RhbGxlZCBhbmQgbG9hZGVkIGFzIG5lY2Vzc2FyeSAoY29kZSBzdXBwcmVzc2VkKS4gCgo8IS0tIFRoZSBgaW5jbHVkZT1GQUxTRWAgb3B0aW9uIHByZXZlbnRzIHlvdXIgY29kZSBmcm9tIGJlaW5nIHNob3duIGF0IGFsbCAtLT4KYGBge3IsIGluY2x1ZGU9RkFMU0V9CiMgVGhpcyBjb2RlIHdpbGwgaW5zdGFsbCByZXF1aXJlZCBwYWNrYWdlcyBpZiB0aGV5IGFyZSBub3QgYWxyZWFkeSBpbnN0YWxsZWQKIyBBTFdBWVMgSU5TVEFMTCBZT1VSIFBBQ0tBR0VTIExJS0UgVEhJUyEKaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCiAgIGxpYnJhcnkoZ2dwbG90MikKfQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCiAgIGxpYnJhcnkodGlkeXZlcnNlKQp9CgppZiAoIXJlcXVpcmUoInBhbmRvYyIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygicGFuZG9jIikKICBsaWJyYXJ5KHBhbmRvYykKfQoKIyBSZXF1aXJlZCBwYWNrYWdlcyBmb3IgTTIwIExJQlMgYW5hbHlzaXMKaWYgKCFyZXF1aXJlKCJybWFya2Rvd24iKSkgewogIGluc3RhbGwucGFja2FnZXMoInJtYXJrZG93biIpCiAgbGlicmFyeShybWFya2Rvd24pCn0KCmlmICghcmVxdWlyZSgic3RyaW5nciIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygic3RyaW5nciIpCiAgbGlicmFyeShzdHJpbmdyKQp9CgppZiAoIXJlcXVpcmUoImdnYmlwbG90IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJnZ2JpcGxvdCIpCiAgbGlicmFyeShnZ2JpcGxvdCkKfQoKaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQogIGxpYnJhcnkoa25pdHIpCn0KCmlmICghcmVxdWlyZSgicnBhcnQiKSkgewogIGluc3RhbGwucGFja2FnZXMoInJwYXJ0IikKICBsaWJyYXJ5KHJwYXJ0KQp9CgppZiAoIXJlcXVpcmUoInJwYXJ0LnBsb3QiKSkgewogIGluc3RhbGwucGFja2FnZXMoInJwYXJ0LnBsb3QiKQogIGxpYnJhcnkocnBhcnQpCn0KCmlmICghcmVxdWlyZSgiY2FyZXQiKSkgewogIGluc3RhbGwucGFja2FnZXMoImNhcmV0IikKICBsaWJyYXJ5KGNhcmV0KQp9CiAgCmlmICghcmVxdWlyZSgiZ2dyZXBlbCIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dyZXBlbCIpCiAgbGlicmFyeShnZ3JlcGVsKQp9CgppZiAoIXJlcXVpcmUoImdlb3NwaGVyZSIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiZ2Vvc3BoZXJlIikKICBsaWJyYXJ5KGdncmVwZWwpCn0KCmlmICghcmVxdWlyZSgiZ2d0ZXJuIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Rlcm4iKQogIGxpYnJhcnkoZ2dyZXBlbCkKfQoKYGBgCgojIDEuMCBQcm9qZWN0IEludHJvZHVjdGlvbgoKVGhlIE1hcnMgUHJvamVjdCBpcyBmb2N1c2VkIG9uIGRhdGEgZnJvbSB0aGUgMjAyMCBNYXJzIFBlcnNldmVyYW5jZSBSb3Zlci4gVGhlIGdvYWwgb2YgdGhlIG1pc3Npb24gaXMgdG8gbG9vayBmb3IgbWljcm9iaWFsIGFuY2llbnQgbGlmZSBvciBmb3JtcyBvZiB3YXRlciBvbiBNYXJzICh0aGluZ3MgdGhhdCBjb3VsZCBzdWdnZXN0IGxpZmUpLiBQZXJzZXZlcmFuY2UgdXNlcyBtdWx0aXBsZSBpbnN0cnVtZW50cywgaW5jbHVkaW5nIFBJWEwgKFBsYW5ldGFyeSBJbnN0cnVtZW50IGZvciBYLVJheSBMaXRob2NoZW1pc3RyeSksIFNIRVJMT0MgKFNjYW5uaW5nIEhhYml0YWJsZSBFbnZpcm9ubWVudHMgd2l0aCBSYW1hbiBhbmQgTHVtaW5lc2NlbmNlIGZvciBPcmdhbmljcyBhbmQgQ2hlbWljYWxzKSBhbmQgU1VQRVJDQU0uIFNVUEVSQ0FNIGhhcyBtdWx0aXBsZSBpbnN0cnVtZW50cyB0aGF0IG1lYXN1cmUgc3BlY3Ryb3Njb3B5IHRvIG1lYXN1cmUgcHJvcGVydGllcyBvZiBtYXRlcmlhbHMgb24gTWFycywgaW5jbHVkaW5nIExJQlMgKExhc2VyLWluZHVjZWQgYnJlYWtkb3duIHNwZWN0cm9zY29weSkuIFRoaXMgbm90ZWJvb2sgd2lsbCBwcmltYXJpbHkgZm9jdXMgb24gdGhlIGRhdGEgd2UgaGF2ZSBiZWVuIGdpdmVuIG9mIFBJWEwgYW5kIExJQlMuICAKCiMgMi4wIE9yZ2FuaXphdGlvbiBvZiBSZXBvcnQKClRoaXMgcmVwb3J0IGlzIG9yZ2FuaXplIGFzIGZvbGxvd3M6IAoKKiBTZWN0aW9uIDMuMC4gIEZpbmRpbmcgMTogTElCUyBhbmQgUElYTCBNYXRjaGluZyAtIFdlIHdlcmUgYWJsZSB0byBjb21iaW5lIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cyBieSBwaWNraW5nIGEgbWF4aW11bSBkaXN0YW5jZSB2YXJpYWJsZSBmcm9tIGEgUElYTCBhYnJhc2lvbiBhbmQgbWF0Y2hpbmcgTElCUyBzYW1wbGVzIHRoYXQgd2VyZSB3aXRoaW4gdGhlIHNldCBkaXN0YW5jZSBvZiBhIFBJWEwgYWJyYXNpb24uICAKCiogU2VjdGlvbiA0LjA6IEZpbmRpbmcgMjogU29pbCBDb21wb3NpdGlvbiBBbmFseXNpcyAtIFVzaW5nIHRoZSBMSUJTIGFuZCBQSVhMIGNvbWJpbmVkIGRhdGEgc2V0LCBJIGNyZWF0ZWQgYSBwbG90IG9mIHRoZSBjb21wb3NpdGlvbiBwZXJjZW50YWdlcyBvZiBjaGVtaWNhbCBjb21wb3VuZHMgc3VjaCBhcyBTaTAyLCBLMjAsIGV0Yy4gdXNpbmcgbG9nIHNjYWxpbmcgdG8gY29tcGFyZSB0aGUgY29tcG9zaXRpb25zIG9mIGEgUElYTCBhYnJhc2lvbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyBzYW1wbGUgY29tcG9zaXRpb25zIChiYXNlZCBvbiB0aGUgTElCUyBzYW1wbGVzIGZvciB4IGRpc3RhbmNlIGF3YXkgZnJvbSBhIFBJWEwgYWJyYXNpb24pLgoKKiBTZWN0aW9uIDUuMCBGaW5kaW5nIDM6IEFuYWx5emluZyBDYXRpb24gQ29tYmluYXRpb25zIHVzaW5nIExJQlMgYW5kIFBJWEwgbWF0Y2hlZCBkYXRhOiBVc2luZyB0aGUgTElCUyBhbmQgUElYTCBjb21iaW5lZCBkYXRhIHNldCwgd2UgY3JlYXRlZCBhIHRlcm5hcnkgcGxvdCB0byBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgTElCUyBzYW1wbGVzIHNvcnRlZCBieSB3aGF0IFBJWEwgYWJyYXNpb24gdGhleSBhcmUgY2xvc2VzdCB0byAoYmFzZWQgb24gYSBjaG9zZW4gZGlzdGFuY2UgdmFyaWFibGUpLgoKKiBTZWN0aW9uIDYuMCBPdmVyYWxsIGNvbmNsdXNpb25zIGFuZCBzdWdnZXN0aW9ucyAKCiogU2VjdGlvbiA3LjAgQXBwZW5kaXggVGhpcyBzZWN0aW9uIGRlc2NyaWJlIHRoZSBmb2xsb3dpbmcgYWRkaXRpb25hbCB3b3JrcyB0aGF0IG1heSBiZSBoZWxwZnVsIGluIHRoZSBmdXR1cmUgd29yazogKmxpc3Qgc3ViamVjdHMqLiAgCgoKIyAzLjAgRmluZGluZyAxOiBQSVhMIGFuZCBMSUJTIE1hdGNoaW5nCgpfR2l2ZSBhIGhpZ2hsZXZlbCBvdmVydmlldyBvZiB0aGUgbWFqb3IgZmluZGluZy4gV2hhdCBxdWVzdGlvbnMgd2VyZSB5b3VyIHRyeWluZyB0byBhZGRyZXNzLCB3aGF0IGFwcHJvYWNoZXMgZGlkIHlvdSBlbXBsb3ksIGFuZCB3aGF0IGhhcHBlbmVkP18KCkZpcnN0bHksIHdlIHdpbGwgYmUgdGFraW5nIGEgbG9vayBhdCBob3cgUElYTCBhbmQgTElCUyBjb3JyZXNwb25kLiBPdXIgZ3JvdXAgZm91bmQgdmVyeSBlYXJseSBpbiBvdXIgcmVzZWFyY2ggdGhhdCB0aGVyZSB3YXNuJ3QgYSBmZWF0dXJlIGFtb25nIHRoZW0gdGhhdCBjYW4gYmUgdXNlZCB0byBtYXRjaCB0aGUgZGF0YSBzZXRzLiBGb3IgZXhhbXBsZSwgdGhlIGNvbHVtbnMgb2YgUElYTCBhcmUgb3JnYW5pemVkIGJ5IGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgYXMgd2VsbCBhcyBzYW1wbGUgbnVtYmVyICgxLTE2KSwgc2FtcGxlIG5hbWUsIGFuZCBhYnJhc2lvbiBuYW1lLiBVbmZvcnR1bmF0ZWx5LCBMSUJTIHdhc24ndCBzb3J0ZWQgdGhlIHNhbWUgd2F5LiBMSUJTIHdhcyBvcmdhbml6ZWQgYnkgdGhlIHNvbCB0aGF0IHRoZSBzYW1wbGUgd2FzIHRha2VuIGF0LiBMSUJTIGlzIGJyb2tlbiB1cCBpbnRvIG1hbnkgZGlmZmVyZW50IHR5cGVzIG9mIHNhbXBsZXMgYXMgd2VsbCwgaW5jbHVkaW5nIHRoZSBmYWN0IGl0IGNhcnJpZXMgYXJvdW5kIGVhcnRoIHJlZmVyZW5jZSBkYXRhIHRvIGJlIHVzZWQgaW4gY29tcGFyaW5nIHdpdGggZGlmZmVyZW50IHNhbXBsZSBzaXRlcy4gVGhhdCBiZWluZyBzYWlkLCBpbiBvcmRlciB0byBtYXRjaCBQSVhMIHRhcmdldHMgdG8gY29ycmVzcG9uZGluZyBMSUJTIHNhbXBsZXMsIE1hcmdvIGFuZCBJIGNyZWF0ZWQgYSBuZXcgZGF0YSBzZXQgdGhhdCBhZGRlZCBhbm90aGVyIG1ldGFkYXRhIGZlYXR1cmUgdG8gUElYTCAobGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBjb29yZGluYXRlcykgd2hpY2ggd2Ugb2J0YWluZWQgZnJvbSB0aGUgQW5hbHlzdCdzIE5vdGVib29rLiBPbmNlIHRoaXMgd2FzIGFkZGVkIGluLCB3ZSByZWFsaXplZCB0aGF0IHRoZSBsb25naXR1ZGUgYW5kIGxhdGl0dWRlIGRpZG4ndCByZWFsbHkgbWF0Y2guIFNvIE1hcmdvIGNyZWF0ZWQgYSBkaXN0YW5jZSBmdW5jdGlvbiB0byBtYXRjaCBMSUJTIHNhbXBsZXMgdG8gUElYTCB0YXJnZXRzIGJhc2VkIG9uIHdoYXRldmVyIGRpc3RhbmNlIGEgcGVyc29uIHNwZWNpZmllcy4gT3JpZ2luYWxseSwgd2Ugc2V0IGl0IHRvIGJlIHJvdW5kZWQgdG8gdGhyZWUgdGhvdXNhbmR0aHMgYW5kIG1hdGNoIGJhc2VkIG9uIHRoYXQuCgpUaGlzIGhlbHBlZCBhbnN3ZXIgdGhlIHF1ZXN0aW9uIG9mIGhvdyBjYW4gd2UgY29ycmVsYXRlIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cyB0byBiZSBhYmxlIHRvIHBsb3QgdGhlbSBvbiB0aGUgc2FtZSBheGlzIG9mIHdoYXRldmVyIHBsb3QgaXMgdHJ5aW5nIHRvIGJlIGNyZWF0ZWQuIEkgd2FzIGN1cmlvdXMgdG8gc2VlIGhvdyBjbG9zZSBQSVhMIHRhcmdldHMgd2VyZSB0byBMSUJTIHNhbXBsZSBzaXRlcyBhcyB3ZWxsIGFzIGhvdyBtYW55IExJQlMgc2FtcGxlcyB3b3VsZCBiZSBhc3NvY2lhdGVkIHdpdGggYSBQSVhMIHRhcmdldCBwZXJoYXBzIHdpdGggYSByYWRpdXMgb2YgNyBvciAxMCBtZXRlcnMuCgojIyAzLjEgRGF0YSwgQ29kZSwgYW5kIFJlc291cmNlcwoKSGVyZSBpcyBhIGxpc3QgZGF0YSBzZXRzLCBjb2RlcywgdGhhdCBhcmUgdXNlZCBpbiB5b3VyIHdvcmsuIEFsb25nIHdpdGggYnJpZWYgZGVzY3JpcHRpb24gYW5kIFVSTCB3aGVyZSB0aGV5IGFyZSBsb2NhdGVkLgoKMS4gcGV0ZXJjLWZpbmFsUHJvamVjdEYyNC5SbWQgKHdpdGgga25pdCBwZGYgYW5kIGh0bWwpIGlzIHRoaXMgbm90ZWJvb2suCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9TdHVkZW50Tm90ZWJvb2tzL0Fzc2lnbm1lbnQwN19EcmFmdEZpbmFsUHJvamVjdE5vdGVib29rL3BldGVyY19maW5hbFByb2plY3RGMjRfcm91Z2hkcmFmdC5SbWRdKGh0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnROb3RlYm9va3MvQXNzaWdubWVudDA3X0RyYWZ0RmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNF9yb3VnaGRyYWZ0LlJtZCkKCjIuIHYxX2xpYnNfdG9fc2FtcGxlLlJkcyBpcyB0aGUgY29tYmluZWQgZGF0YSBzZXQgb2YgUElYTCBhbmQgTElCUyB0aGF0IGluY2x1ZGVzIHRoZSBkaXN0YW5jZSBmcm9tIGEgUElYTCBhYnJhc2lvbiB0byBhIExJQlMgc2FtcGxlLiAgCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9TdHVkZW50RGF0YS92MV9saWJzX3RvX3NhbXBsZS5SZHNdKGh0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnREYXRhL3YxX2xpYnNfdG9fc2FtcGxlLlJkcykuIAoKRmlyc3RseSwgd2Ugc2V0IHRoZSBudW1iZXIgb2YgbWV0ZXJzIGRpc3RhbmNlIHRocmVzaG9sZCBiZXR3ZWVuIGEgUElYTCBhYnJhc2lvbiBhbmQgTElCUyBzYW1wbGUuIFdpdGhpbiB0aGUgdjFfbGlic190b19zYW1wbGUuUmRzLCB3aGljaCBNYXJnbyBhbmQgSSBjb2xsYWJvcmF0ZWQgb24gdGhlcmUgaXMgYSBkaXN0YW5jZSB2YXJpYWJsZSB0aGF0IGlzIHNldCB2aWEgYSBmdW5jdGlvbiB0aGF0IE1hcmdvIGNyZWF0ZWQgdG8gbWVhc3VyZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiBhIFBJWEwgYWJyYXNpb24gYW5kIExJQlMgc2FtcGxlIHVzaW5nIHRoZWlyIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgY29vcmRpbmF0ZXMuIApgYGB7cn0KbWV0ZXJzIDwtIDcKYGBgCgpUbyBwcmVwYXJlIHRoZSBkYXRhLCB3ZSB3aWxsIGxvYWQgaW4gdGhlIHYxX2xpYnNfdG9fc2FtcGxlLlJkcywgZ3JvdXAgYnkgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBvZiBMSUJTLCBhbmQgZmlsdGVyIG91dCBldmVyeSBMSUJTIHNhbXBsZSB0aGF0IGhhcyBhIGxhcmdlciBkaXN0YW5jZSBmcm9tIGl0cyBjb3JyZXNwb25kaW5nIFBJWEwgYWJyYXNpb24gdGhhbiBzcGVjaWZpZWQgaW4gdGhlIGNob3NlbiBkaXN0YW5jZSAobWV0ZXIpIHZhbHVlLiBJbiBvcmRlciB0byBtYWtlIGEgc2NhdHRlciBwbG90IG9mIHRoZSBMSUJTIGFuZCBQSVhMIHBvaW50cywgd2Ugd2lsbCBjcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSBvZiBlYWNoIHVuaXF1ZSBQSVhMIGFicmFzaW9uIGFuZCBpdHMgY29vcmRpbmF0ZXMuIFRoYXQgaXMgdGhlIHVuaXF1ZV9waXhsIGRhdGEgZnJhbWUgd2hpY2ggd2lsbCBiZSB1c2VkIHRvIHBsb3QgdGhlIFBJWEwgYWJyYXNpb24gY29vcmRpbmF0ZXMuCgpgYGB7ciB9CmxpYnNfdG9fc2FtcGxlIDwtIHJlYWRSRFMoIn4vREFSLU1hcnMtRjI0L1N0dWRlbnREYXRhL3YxX2xpYnNfdG9fc2FtcGxlLlJkcyIpCiNtYWtlIGEgZmlsdGVyZWQgZGF0YSBmcmFtZSB0aGF0IHBpY2tzIHRoZSBtYXggcG9pbnQgb3V0IG9mIGFsbCBsaWJzIHNhbXBsZXMgYXQgYSBjZXJ0YWluIHRhcmdldCAKIyBmb3Igc2ltcGxpY2l0eQpkZl9maWx0ZXJlZCA8LSBsaWJzX3RvX3NhbXBsZSAlPiUKICBncm91cF9ieShMYXQubGlicywgTG9uLmxpYnMpICU+JQogIGZpbHRlcihQb2ludC5saWJzID09IG1heChQb2ludC5saWJzKSkgJT4lCiAgdW5ncm91cCgpCmRmX2Rpc3RhbmNlX2ZpbHRlciA8LSBkZl9maWx0ZXJlZFtkZl9maWx0ZXJlZCREaXN0YW5jZSA8PSBtZXRlcnMsXQoKI21ha2UgYSBkYXRhIGZyYW1lIHdpdGggdGhlIHVuaXF1ZSBwaXhsIGNvb3JkaW5hdGVzIHNpbmNlIHRoZXkgYXJlIGluIHBhaXJzIG9mIGlkZW50aWNhbCBsYXQvbG9uCnVuaXF1ZV9waXhsIDwtIGRmX2ZpbHRlcmVkICU+JQogIHNlbGVjdChMYXQucGl4bCwgTG9uLnBpeGwsIEFicmFzaW9uLnBpeGwpICU+JSBkaXN0aW5jdCgpCmBgYAoKCiMjIDMuMiBDb250cmlidXRpb24KClRoZSBsb2dpc3RpY3Mgb2YgZmlsdGVyaW5nIHRoZSBvcmlnaW5hbCBkYXRhIHNldCBpcyBteSB3b3JrLiBQcmV2aW91c2x5LCBJIGhhZCB0byBkbyBhIGxvdCBtb3JlIGZpbHRlcmluZyBpbiBvcmRlciB0byBjaG9vc2UgdGhlIGRpc3RhbmNlIGFuZCBnZXQgdW5pcXVlIExJQlMgcG9pbnRzIGluIG9yZGVyIHRvIG5vdCBwdXQgdG9vIG1hbnkgcG9pbnRzIG9uIHRoZSBzY2F0dGVycGxvdC4gTWFyZ28gYW5kIEkgd29ya2VkIHRvZ2V0aGVyIHRvIGNyZWF0ZSB0aGUgZGF0YSBzZXQgdGhhdCBJIHVzZSBpbiB0aGlzIHNlY3Rpb24gKHYxX2xpYnNfdG9fc2FtcGxlLlJkcykgYnkgZGVjaWRpbmcgaG93IHRvIG1hdGNoIHVwIExJQlMgdG8gY2VydGFpbiBQSVhMIGFicmFzaW9ucy4gTWFyZ28gY3JlYXRlZCB0aGUgZGlzdGFuY2UgZnVuY3Rpb24gdG8gZmluZCB0aGUgZGlzdGFuY2UgYmV0d2VlbiBQSVhMIGFicmFzaW9ucyBhbmQgTElCUyBzYW1wbGVzIGFuZCBhZGRlZCB0aGF0IGNvbHVtbiB0byB0aGUgZGF0YSBzZXQuIFRoZW4sIERvbmEgZml4ZWQgYWxsIHRoZSBuYW1pbmcgY29udmVudGlvbnMgaW4gdGhlIGRhdGEgc2V0IGluIG9yZGVyIHRvIGhhdmUgY29uc2lzdGVuY3kgYW5kIG1ha2UgaXQgZWFzeSB0byB0ZWxsIHdoaWNoIHZhcmlhYmxlIHdhcyBvcmlnaW5hbGx5IGZyb20gZWFjaCBkYXRhIHNldCAoZXguIE5hbWUucGl4bCwgVGFyZ2V0LmxpYnMpLiBJIHRoZW4gdXNlZCB0aGUgZGF0YSB0byBjcmVhdGUgcGxvdHMgYW5kIGFuYWx5emUuIEJlbG93IGlzIGEgc2NhdHRlcnBsb3Qgc2hvd2Nhc2luZyB0aGUgZGlzdHJpYnV0aW9uIG9mIFBJWEwgYWJyYXNpb25zIGFuZCBjb3JyZXNwb25kaW5nIExJQlMgc2FtcGxlcyBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIG1heCBkaXN0YW5jZSBiZXR3ZWVuIHRoZW0uIAoKCiMjIDMuMyBNZXRob2RzIERlc2NyaXB0aW9uIAoKSSBjaG9zZSB0byB1c2UgZ2dwbG90IHRvIGRpc3BsYXkgdGhlIExJQlMgYW5kIFBJWEwgZGF0YSBmb3IgZWFzaWVyIGFuYWx5c2lzIG9mIHNlZWluZyBob3cgbWFueSBMSUJTIHNhbXBsZXMgYWxpZ24gd2l0aCBkaWZmZXJlbnQgUElYTCBhYnJhc2lvbnMuIEl0IHdhcyB2ZXJ5IGludGVyZXN0aW5nIHRvIGNoYW5nZSBhcm91bmQgdGhlIG1heCBkaXN0YW5jZSBhbmQgc2VlIHdoaWNoIGFsaWduZWQgd2l0aCB3aGljaCBhYnJhc2lvbi4gSW4gdGVybXMgb2YgZXhlY3V0aW9uLCBpdCB0b29rIG1lIGEgYml0IG9mIHRpbWUgdG8gb3JnYW5pemUgYWxsIG9mIHRoZSB0aG91Z2h0cyBNYXJnbyBhbmQgSSBoYWQgb24gaG93IHRvIGNyZWF0ZSBhbmQgbWFuYWdlIHRoaXMgZGF0YSBzZXQuIE9yaWdpbmFsbHksIHdlIGhhZCByb3VuZGVkIHRoZSBkaXN0YW5jZXMgdG8gdGhlIG5lYXJlc3QgdGhvdXNhbmR0aCB0byBtYXRjaCB0aGVtLCBhbmQgdGhlbiB3ZXJlIHBsb3R0aW5nIHRoYXQgd2F5LiBIb3dldmVyLCB0aGF0IGxlZnQgYSBsb3Qgb2Ygcm9vbSBmb3IgZXJyb3IgYW5kIHdhc24ndCBhcyBhY2N1cmF0ZS4gQ3JlYXRpbmcgYSBkaXN0YW5jZSBmdW5jdGlvbiBhbGxvd3MgZm9yIHRoZSBzY2llbnRpc3Qgb3IgcGVyc29uIHVzaW5nIHRoZSBNYXJzIE1pc3Npb24gTWluZGVyIEFwcCB0byBjaG9vc2Ugd2hhdGV2ZXIgZGlzdGFuY2UgdGhleSB3b3VsZCBsaWtlIGFuZCBhbGxvd3MgZm9yIG11Y2ggbW9yZSBmdW5jdGlvbmFsaXR5LiBNb2RpZnlpbmcgdGhlIGRhdGEgc2V0IG1vcmUgZW5kZWQgdXAgYmVpbmcgbW9yZSBlZmZpY2llbnQgdGhhbiBhZGRpbmcgc21hbGwgZWRpdHMgYXMgSSB3YXMgbWFraW5nIG15IHBsb3RzIHdoaWNoIHdhcyBvcmlnaW5hbGx5IG1ha2luZyBtZSBjcmF6eSAoYXMgaW4gY2hhbmdpbmcgdmFyaWFibGUgdHlwZXMgaWYgdGhleSB3ZXJlbid0IHdoYXQgdGhleSB3ZXJlIHN1cHBvc2VkIHRvIGJlKS4gSW4gdGhlIGVuZCwgSSBsZWFybmVkIGEgbG90IGFib3V0IGRhdGEgb3JnYW5pemF0aW9uIGFuZCB0aGF0IGNvbnNpc3RlbmN5IGFuZCBzdGF5aW5nIG9yZ2FuaXplZCBpcyBrZXkgYW5kIHNhdmVzIGEgbG90IG9mIHRpbWUgbGF0ZXIgb24uCgoKIyMgMy40IFJlc3VsdCBhbmQgRGlzY3Vzc2lvbiAKClRvIGNyZWF0ZSBhIHBsb3Qgb2YgdGhlIExJQlMgYW5kIFBJWEwgZGF0YSBvcmdhbml6ZWQgYnkgd2hhdCBMSUJTIHNhbXBsZXMgYWxpZ24gd2l0aCB3aGF0IGFicmFzaW9ucywgZmlyc3QgcGxvdHRlZCB0aGUgTElCUyBzYW1wbGVzIGNvbG9yZWQgYnkgd2hhdCBQSVhMIGFicmFzaW9uIHRoZXkgd2VyZSBjbG9zZXN0IHRvLCBhbmQgdGhlbiBwbG90dGVkIHRoIFBJWEwgYWJyYXNpb25zIGFzIHJlZCBzdGFycyBvbiB0aGUgcGxvdCB0byBzaG93IHdoZXJlIHRoZSBQSVhMIGFicmFzaW9ucyB3ZXJlIHJlbGF0aXZlIHRvIHRoZSBMSUJTIHNhbXBsZXMuCgpgYGB7ciB9CiNwbG90IG9mIGxpYnMgYW5kIHBpeGwgZGF0YSBieSBsYXQvbG9uCmdncGxvdChkYXRhID0gZGZfZGlzdGFuY2VfZmlsdGVyKSArCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBMb24ubGlicywgeSA9IExhdC5saWJzLCBjb2xvciA9IEFicmFzaW9uLnBpeGwpKSArICAgICAgICAgICAgICAgICAjIENvbG9yIGJ5IGFicmFzaW9uCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBMb24ucGl4bCwgeSA9IExhdC5waXhsKSwgZGF0YSA9IHVuaXF1ZV9waXhsLCBjb2xvciA9ICJyZWQiLCBzaGFwZSA9IDMsIHNpemUgPSAzKSArICMgRml4ZWQgY29sb3IgZm9yIHVuaXF1ZV9waXhsIHBvaW50cwogIGdlb21fdGV4dF9yZXBlbChtYXBwaW5nID0gYWVzKHggPSBMb24ucGl4bCwgeSA9IExhdC5waXhsLCBsYWJlbCA9IEFicmFzaW9uLnBpeGwpLCBkYXRhID0gdW5pcXVlX3BpeGwsCiAgICAgICAgICAgICAgICAgIHZqdXN0ID0gMiwgY29sb3IgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiTElCUyBTYW1wbGVzIGFuZCBQSVhMIEFicmFzaW9ucyB3aXRoaW4iLCBtZXRlcnMsICJtZXRlcnMiKSwKICAgICAgIHggPSAiTG9uZ2l0dWRlIiwKICAgICAgIHkgPSAiTGF0aXR1ZGUiLAogICAgICAgY29sb3IgPSAiUElYTCBBYnJhc2lvbiIsCiAgICAgICBjYXB0aW9uID0gIkRhdGEgY29sbGVjdGVkIHVzaW5nIExJQlMgYW5kIFBJWEwgaW5zdHJ1bWVudHMgb24gUGVyc2VydmVyYW5jZSByb3Zlci5cbiBTaG93cyBQSVhMIGFicmFzaW9ucyBwbG90dGVkIGFzIHJlZCBzdGFycyxcbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyBzYW1wbGVzIGNvbG9yZWQgYnkgdGhlaXIgY2xvc2VzdCBQSVhMIGFicmFzaW9uLiIpKyAgICAgICAgICAjIExhYmVsIGZvciB0aGUgY29sb3IgbGVnZW5kIAogIyBDZW50ZXIgdGhlIGNhcHRpb24gb24gdGhlIGxlZnQgc2lkZQogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkgICMgQWxpZ25zIGNhcHRpb24gdG8gdGhlIGxlZnQKICApCgojYWRkIGxlZ2VuZCBmb3IgUElYTCBpZGsgd2h5IGl0J3Mgbm90IHdvcmtpbmcKYGBgCldoZW4gbG9va2luZyBhdCB0aGlzIHBsb3QsIHRoZSBkYXRhIGZyYW1lIG9mIHRoZSBmaWx0ZXJlZCBMSUJTIGRhdGEgKGRmX2Rpc3RhbmNlX2ZpbHRlcikgYmFzZWQgb24gZGlzdGFuY2VzIHRvIGEgUElYTCBhYnJhc2lvbiBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gNyBtZXRlcnMgZmluZHMgMyBMSUJTIHNhbXBsZXMgY29ycmVzcG9uZGluZyB0byBBbGZhbGZhLCAyIGNvcnJlc3BvbmRpbmcgdG8gQmVsbGVncmFkZSwgMyBjb3JyZXNwb25kaW5nIHRvIERvdXJiZXMsIDcgY29ycmVzcG9uZGluZyB0byBOb3ZhcnVwdGEsIDQgY29ycmVzcG9uZGluZyB0byBRdWFydGllciwgYW5kIDkgY29ycmVzcG9uZGluZyB0byBUaG9ybnRvbiBHYXAuIAoKIyMgMy41IENvbmNsdXNpb25zLCBMaW1pdGF0aW9ucywgYW5kIEZ1dHVyZSBXb3JrLgoKSSBiZWxpZXZlIG15IGZpbmRpbmdzIG1ha2UgaXQgdmVyeSBlYXN5IGZvciByZXNlYXJjaGVycyBhbmQgc2NpZW50aXN0cyB0byBoYXZlIGEgdmlzdWFsaXphdGlvbiBvZiBQSVhMIGFuZCBMSUJTIHNhbXBsZXMgdGhhdCB0aGV5IHdhbnQgdG8gc2VlIGJhc2VkIG9uIHdoYXQgbWF4IGRpc3RhbmNlIHRoZXkgYXJlIGZvY3VzaW5nIG9uIHdoZW4gZXhhbWluaW5nIFBJWEwgYW5kIExJQlMgdG9nZXRoZXIuIEZvciBmdXR1cmUgd29yaywgSSB0aGluayBhcyBtb3JlIGNvb3JkaW5hdGVzIGFuZCBkYXRhIGlzIGFkZGVkIHRvIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cyBhcyB0aGV5IGJlY29tZSBhdmFpbGFibGUgZnJvbSBOQVNBIHRoaXMgd2lsbCBjb250aW51ZSB0byBiZSBidWlsdCB1cG9uIGFuZCBhbHRob3VnaCBpdCBpc24ndCBzdXBlciBjb21wbGljYXRlZCBvZiBhIHBsb3QsIGl0IHByb3ZpZGVzIGEgdmVyeSBuZWNlc3NhcnkgY29udGV4dCB0byB2aXN1YWxpemUgUElYTCBhbmQgTElCUy4gSSBkaWRuJ3QgZmluZCBtYW55IGxpbWl0YXRpb25zIGluIHRoaXMgcGxvdCBhcyBpdCBiYXNpY2FsbHkgaXMgb25seSBwcm92aWRpbmcgYW4gZWFzeSB2aXN1YWwgb2YgdGhlIFBJWEwgYW5kIExJQlMgZGF0YSB0b2dldGhlci4KCiMgNC4wIEZpbmRpbmcgMjogU29pbCBDb21wb3NpdGlvbiBBbmFseXNpcwpfR2l2ZSBhIGhpZ2hsZXZlbCBvdmVydmlldyBvZiB0aGUgbWFqb3IgZmluZGluZy4gV2hhdCBxdWVzdGlvbnMgd2VyZSB5b3VyIHRyeWluZyB0byBhZGRyZXNzLCB3aGF0IGFwcHJvYWNoZXMgZGlkIHlvdSBlbXBsb3ksIGFuZCB3aGF0IGhhcHBlbmVkP18KClVzaW5nIHRoZSBMSUJTIGFuZCBQSVhMIGNvbWJpbmVkIGRhdGEgc2V0LCBJIGNyZWF0ZWQgYSBwbG90IG9mIHRoZSBjb21wb3NpdGlvbiBwZXJjZW50YWdlcyBvZiBjaGVtaWNhbCBjb21wb3VuZHMgc3VjaCBhcyBTaTAyLCBLMjAsIGV0Yy4gdXNpbmcgbG9nIHNjYWxpbmcgdG8gY29tcGFyZSB0aGUgY29tcG9zaXRpb25zIG9mIGEgUElYTCBhYnJhc2lvbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyBzYW1wbGUgY29tcG9zaXRpb25zIChiYXNlZCBvbiB0aGUgTElCUyBzYW1wbGVzIGZvciB4IGRpc3RhbmNlIGF3YXkgZnJvbSBhIFBJWEwgYWJyYXNpb24pLiBUaGUgcXVlc3Rpb24gSSB3YXMgdHJ5aW5nIHRvIGFuc3dlciB3YXMgaG93IGRvZXMgdGhlIExJQlMgZGF0YSBvZiBhIGNlcnRhaW4gYXJlYSBjb21wYXJlIHRvIHRoZSBQSVhMIGRhdGEgb2YgdGhhdCBhcmVhPyBCeSBsb29raW5nIGF0IHRoZSBjb21wb3NpdGlvbiBvZiB0aGUgc29pbCBpbiBjZXJ0YWluIGxvY2F0aW9ucywgd2UgY2FuIGNvbXBhcmUgdGhlIGRpZmZlcmVuY2VzIGluIHRoZSBQSVhMIGFicmFzaW9uIGFuZCByZWxhdGluZyBMSUJTIHNhbXBsZXMgZm9yIGEgY2VydGFpbiBhcmVhIHV0aWxpemluZyB0aGUgc2FtZSBkYXRhIHNldCAodjFfbGlic190b19zYW1wbGUuUm1kKS4gSW4gb3JkZXIgdG8gYWNjb21wbGlzaCB0aGlzLCAKCgojIyA0LjEgRGF0YSwgQ29kZSwgYW5kIFJlc291cmNlcwpIZXJlIGlzIGEgbGlzdCBkYXRhIHNldHMsIGNvZGVzLCB0aGF0IGFyZSB1c2VkIGluIHlvdXIgd29yay4gQWxvbmcgd2l0aCBicmllZiBkZXNjcmlwdGlvbiBhbmQgVVJMIHdoZXJlIHRoZXkgYXJlIGxvY2F0ZWQuCgoxLiBwZXRlcmNfZmluYWxQcm9qZWN0RjI0LlJtZCAod2l0aCBrbml0IHBkZiBhbmQgaHRtbCkgaXMgdGhpcyBub3RlYm9vay4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnROb3RlYm9va3MvQXNzaWdubWVudDA3X0RyYWZ0RmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNF9yb3VnaGRyYWZ0LlJtZF0oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDdfRHJhZnRGaW5hbFByb2plY3ROb3RlYm9vay9wZXRlcmNfZmluYWxQcm9qZWN0RjI0X3JvdWdoZHJhZnQuUm1kKQoKMi4gcGV0ZXJjX2Fzc2lnbm1lbnQ1LlJtZCAod2l0aCBrbml0IHBkZiBhbmQgaHRtbCkgd2hpY2ggaXMgbXkgcHJldmlvdXMgbm90ZWJvb2suCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L3RyZWUvbWFpbi9TdHVkZW50Tm90ZWJvb2tzL0Fzc2lnbm1lbnQwNS9wZXRlcmNfYXNzaWdubWVudDA1LlJtZF0oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC90cmVlL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDUvcGV0ZXJjX2Fzc2lnbm1lbnQwNS5SbWRdKQoKMy4gc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcyB3aGljaCBpcyB0aGUgb3JpZ2luYWwgTElCUyBkYXRhIGdpdmVuIHRvIG91ciByZXNlYXJjaCBncm91cC4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkc10oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vRGF0YS9zdXBlcmNhbV9saWJzX21vY19sb2MuUmRzKQoKNC4gcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzLCB3aGljaCBpcyB0aGUgZGF0YSBzZXQgY29udGFpbmluZyB0aGUgUElYTCBkYXRhLCBzb2wsIGFuZCBjb29yZGluYXRlcy4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnREYXRhL3BpeGxfc29sX2Nvb3JkaW5hdGVzLlJkc10oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudERhdGEvcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzKQoKNC4gTElCU190cmFpbmluZ19zZXRfcXVhcnRpbGVzLlJkcyBpcyB0aGUgZGF0YSB3aXRoIGVhcnRoIHF1YXJ0aWxlIHJlZmVyZW5jZSBkYXRhLgpbaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vRGF0YS9MSUJTX3RyYWluaW5nX3NldF9xdWFydGlsZXMuUmRzXShodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9EYXRhL0xJQlNfdHJhaW5pbmdfc2V0X3F1YXJ0aWxlcy5SZHMpLiAKClRvIHByZXBhcmUgdGhlIGRhdGEsIEkgc3RhcnQgYnkgbG9hZGluZyBpbiB0aGUgTElCUyBkYXRhLiBUaGVuLCB3ZSBkcm9wIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gY29sdW1ucyBhbmQgc3VtIG9mIHBlcmNlbnRhZ2UgY29sdW1ucyBsZWF2aW5nIHVzIHdpdGgganVzdCB0aGUgd2VpZ2h0ZWQgY29tcG9zaXRpb24gaW4gdGVybXMgb2YgbnVtZXJpY2FsIGRhdGEuIFdlIGFsc28gcmVtb3ZlIHRoZSBzY2N0IHZhbHVlcywgYXMgdGhvc2UgdmFsdWVzIGFyZSB0aGUgb25lcyB0aGF0IGFyZSBlYXJ0aCByZWZlcmVuY2Ugc2FtcGxlcyB0aGF0IFBlcnNlcnZlcmFuY2UgY2FycmllcyB3aXRoIGl0LiBUaGVyZWZvcmUsIHRoZXkgd2lsbCBub3QgYmUgdmVyeSByZWxldmFudCB3aGVuIHBsb3R0aW5nIHRoZSBMSUJTIGRhdGEgYXMgd2UgYXJlIGZvY3VzZWQgb24gdGhlIE1hcnMgc29pbCBjb21wb3NpdGlvbnMuCgpgYGB7cn0KI0VhcnRoIHF1YXJ0aWxlcwplYXJ0aHF1YXJ0aWxlcy5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9EYXRhL0xJQlNfdHJhaW5pbmdfc2V0X3F1YXJ0aWxlcy5SZHMiKQojTG9hZCBpbiBMSUJTIGRhdGEKbGlicy5kZiA8LSByZWFkUkRTKCIvYWNhZGVtaWNzL01BVFAtNDkxMC1GMjQvREFSLU1hcnMtRjI0L0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcyIpCiNEcm9wIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gZmVhdHVyZXMsIHRoZSBzdW0gb2YgdGhlIHBlcmNlbnRhZ2VzLCAKI3RoZSBkaXN0YW5jZSwgYW5kIHRoZSB0b3RhbCBmcmVxdWVuY2llcwpsaWJzLmRmIDwtIGxpYnMuZGYgJT4lIAogIHNlbGVjdCghKGMoZGlzdGFuY2VfbW0sVG90LkVtLixTaU8yX3N0ZGV2LFRpTzJfc3RkZXYsQWwyTzNfc3RkZXYsRmVPVF9zdGRldiwKICAgICAgICAgICAgIE1nT19zdGRldixOYTJPX3N0ZGV2LENhT19zdGRldixLMk9fc3RkZXYsVG90YWwpKSkKIyBDb252ZXJ0IHRoZSBwb2ludHMgdG8gbnVtZXJpYwpsaWJzLmRmJHBvaW50IDwtIGFzLm51bWVyaWMobGlicy5kZiRwb2ludCkKbGlicy5kZlssNjoxM10gPC0gc2FwcGx5KGxpYnMuZGZbLDY6MTNdLGFzLm51bWVyaWMpCiNyZW1vdmUgdGhlIHNjY3QvcmVmZXJlbmNlIHNhbXBsZXMKbGlicy5kZjwtbGlicy5kZiU+JQogIGZpbHRlcighKGdyZXBsKCJzY2N0IiwgdGFyZ2V0KSkpCiNhZGQgYSBjb2x1bW4gdG8gaW5kaWNhdGUgdGhlIG5lYXJlc3QgcGl4bApsaWJzLmRmPC1jYmluZChuZWFyZXN0cGl4bD0wLGxpYnMuZGYpCiNtYWtlIGEgZGF0YWZyYW1lIG9mIGp1c3QgdGhlIExJQlMgTGF0L0xvbmcgYW5kIHRhcmdldCBuYW1lIGFuZCByZW1vdmUgZHVwbGljYXRlcwpsaWJzdGFyZ2V0cy5kZjwtbGlicy5kZlssYygxLDMsNCw1KV0KbGlic3RhcmdldHMuZGY8LWRpc3RpbmN0KGxpYnN0YXJnZXRzLmRmKQpgYGAKClNldCBtZXRlcnMgYW5kIGNob3NlbiBhYnJhc2lvbiB0byBhY3QgYXMgYSBzbGlkZXIgaW4gdGhlIDJkIGFwcC4KYGBge3J9CiNDaG9vc2UgbWF4IGRpc3RhbmNlIHZhcmlhYmxlIGJldHdlZW4gUElYTCBhbmQgTElCUyBkYXRhCm1ldGVycyA9IDcKI0Nob29zZSBQSVhMIGFicmFzaW9uIHlvdSB3YW50IHRvIGxvb2sgYXQKYWJyYXNpb25fbmFtZSA9ICJBbGZhbGZhIgpgYGAKCk5leHQsIHdlIGxvYWQgaW4gdGhlIFBJWEwgZGF0YS4gV2UgcmVtb3ZlIHRoZSBhdG1vc3BoZXJpYyBzYW1wbGUgYW5kIG9ubHkgc2VsZWN0IG9uZSBQSVhMIHNhbXBsZSBvZiBlYWNoIGFicmFzaW9uLgpgYGB7ciwgZGF0YTAyfQojcmVhZCBpbiBwaXhsIGRhdGEgd2l0aCBsYXQvbG9uZwpwaXhsLmRmPC1yZWFkUkRTKCIvYWNhZGVtaWNzL01BVFAtNDkxMC1GMjQvREFSLU1hcnMtRjI0L1N0dWRlbnREYXRhL3BpeGxfc29sX2Nvb3JkaW5hdGVzLlJkcyIpCiNpbmNsdWRlIG9ubHkgcGl4bCBtZXRhZGF0YQpwaXhsLmRmPC1waXhsLmRmICU+JQogIHNlbGVjdChjKDEsMiwxOSwyMCwyMikpCiNjb252ZXJ0IExhdC9Mb25nIHRvIG51bWVyaWMKcGl4bC5kZiRMYXQgPC0gYXMubnVtZXJpYyhwaXhsLmRmJExhdCkKcGl4bC5kZiRMb25nIDwtIGFzLm51bWVyaWMocGl4bC5kZiRMb25nKQojcmVtb3ZlIHJvd3Mgc28gd2Ugb25seSBoYXZlIG9uZSBzYW1wbGUgcGVyIGFicmFzaW9uIGFuZCByZW1vdmUgYXRtb3NwaGVyaWMgc2FtcGxlCnBpeGwuZGY8LXBpeGwuZGZbYygyLDQsNiw4LDEwLDEyLDE0LDE2KSxdCmBgYAoKTmV4dCwgd2Ugd2lsbCBpbml0aWFsaXplIGEgZGlzdGFuY2UgdmFyaWFibGUgKHRvIGluZGljYXRlIGRpc3RhbmNlIGJldHdlZW4gUElYTCBhYnJhc2lvbiBhbmQgTElCUyB0YXJnZXQpIGFuZCBhbHNvIGluaXRpYWxpemUgZWFjaCBQSVhMIGFicmFzaW9uLCB3aGljaCB3aWxsIGJlIHVzZWQgdG8gbWFyayB3aGljaCBQSVhMIGFicmFzaW9uIHRoZSBMSUJTIHNhbXBsZSBpcyBjbG9zZXN0IHRvIGJ5IHVzaW5nIGEgZmFjdG9yIG9mIDAgb3IgMS4gCmBgYHtyfQpsaWJzdGFyZ2V0cy5kZjwtY2JpbmQobGlic3RhcmdldHMuZGYsIkRpc3RhbmNlIj0wLCJCZWxsZWdyYWRlIj0wLCJEb3VyYmVzIj0wLCJRdWFydGllciI9MCwiQWxmYWxmYSI9MCwiVGhvcm50b25HYXAiPTAsIkJlcnJ5IEhvbGxvdyI9MCwiTm92YXJ1cHRhIj0wLCJVZ2FuaWsgSXNsYW5kIj0wKQpgYGAKClRoZSBkaXN0YW5jZSBmdW5jdGlvbiBiZWxvdyB3aWxsIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIExJQlMgdGFyZ2V0IGFuZCBhbGwgdGhlIFBJWEwgYWJyYXNpb25zLCBhbmQgcGljayB0aGUgc21hbGxlc3QgZGlzdGFuY2UgdG8gcGljayB0aGUgY2xvc2VzdCBQSVhMIGFicmFzaW9uIHRvIHRoYXQgTElCUyB0YXJnZXQuCmBgYHtyfQpmb3IoaSBpbiAxOm5yb3cobGlic3RhcmdldHMuZGYpKSB7CiAgICBsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldPC1jKGRpc3RIYXZlcnNpbmUocGl4bC5kZlsxLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZlsyLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZlszLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls0LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls1LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls2LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls3LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls4LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSkpCiAgICAKICAgIGxpYnN0YXJnZXRzLmRmW2ksMV08LXdoaWNoLm1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQogICAgbGlic3RhcmdldHMuZGZbaSw1XTwtbWluKGxpYnN0YXJnZXRzLmRmW2ksYyg2OjEzKV0pCn0KbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw8LWFzLmZhY3RvcihsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCkKbGV2ZWxzKGxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsKTwtKGMoIkJlbGxlZ3JhZGUiLCJEb3VyYmVzIiwiUXVhcnRpZXIiLCJBbGZhbGZhIiwiVGhvcm50b25HYXAiLCJCZXJyeSBIb2xsb3ciLCJOb3ZhcnVwdGEiLCJVZ2FuaWsgSXNsYW5kIikpCmBgYAoKQmVsb3cgaXMgYW5vdGhlciBpbml0aWFsaXplciBmb3IgdGhlIFBJWEwgYWJyYXNpb24gZGF0YS4gVGhpcyBzZXRzIHRoZSB2YXJpYWJsZXMgZm9yIGVhY2ggUElYTCBhYnJhc2lvbi4KYGBge3J9CkJlbGxlZ3JhZGU8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVsbGVncmFkZSIsXSR0YXJnZXQKRG91cmJlczwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJEb3VyYmVzIixdJHRhcmdldApRdWFydGllcjwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJRdWFydGllciIsXSR0YXJnZXQKQWxmYWxmYTwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJBbGZhbGZhIixdJHRhcmdldApUaG9ybnRvbkdhcDwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJUaG9ybnRvbkdhcCIsXSR0YXJnZXQKQmVycnlIb2xsb3c8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVycnkgSG9sbG93IixdJHRhcmdldApOb3ZhcnVwdGE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iTm92YXJ1cHRhIixdJHRhcmdldApVZ2FuaWtJc2xhbmQ8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVWdhbmlrIElzbGFuZCIsXSR0YXJnZXQKYGBgCgpOZXh0LCB3ZSBmaWx0ZXIgb3V0IHRoZSBMSUJTIHRhcmdldHMgdGhhdCBhcmUgbm90IHdpdGhpbiB0aGUgc3BlY2lmaWVkIGRpc3RhbmNlIHZhcmlhYmxlLiBUaGVuLCB3ZSBtZXJnZSB0aGUgTElCUyBkYXRhIHdpdGggdGhlIHJlc3BlY3RpdmUgUElYTCBhYnJhc2lvbiBieSBtdXRhdGluZyBhbmQgYWRkaW5nIGFuIGFicmFzaW9uIGNvbHVtbiB0aGF0IGhhcyB0aGUgYWJyYXNpb24gbmFtZSBjbG9zZXN0IHRvIGVhY2ggTElCUyB0YXJnZXQuIFdlIGFsc28gYWRkIGEgY29sdW1uLCBMSUJTIG9yIFBJWEwsIHdoaWNoIGRlbm90ZXMgaWYgdGhlIHJvdyBvZiBkYXRhIGlzIGZyb20gdGhlIFBJWEwgYW5kIExJQlMgZGF0YSBzZXRzLgpgYGB7cn0KaW5jbHVkZWQubGliczwtKGxpYnN0YXJnZXRzLmRmJT4lCiAgZmlsdGVyKERpc3RhbmNlPG1ldGVycykpJHRhcmdldApsaWJzLm1hdHJpeCA8LWxpYnMuZGYgJT4lCiAgZmlsdGVyKHRhcmdldCAlaW4lIGluY2x1ZGVkLmxpYnMpCmxpYnMubWF0cml4IDwtIGxpYnMubWF0cml4WyxjKDUsNzoxNCldCmxpYnMubWF0cml4PC1saWJzLm1hdHJpeFssYygxOjIsNDo5LDMpXQpsaWJzLm1hdHJpeDwtY2JpbmQoIkFicmFzaW9uIj0wLGxpYnMubWF0cml4KQpsaWJzLm1hdHJpeDwtbGlicy5tYXRyaXglPiUKICBtdXRhdGUoQWJyYXNpb24gPSBpZmVsc2UodGFyZ2V0JWluJUFsZmFsZmEsIkFsZmFsZmEiLCAKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgQmVsbGVncmFkZSwgIkJlbGVncmFkZSIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIEJlcnJ5SG9sbG93LCAiQmVycnkgSG9sbG93IiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgRG91cmJlcywgIkRvdXJiZXMiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBOb3ZhcnVwdGEsICJOb3ZhcnVwdGEiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBRdWFydGllciwgIlF1YXJ0aWVyIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgVGhvcm50b25HYXAsICJUaG9ybnRvbkdhcCIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFVnYW5pa0lzbGFuZCwgIlVnYW5payBJc2xhbmQiLEFicmFzaW9uKSkpKSkpKSkpCmxpYnMubWF0cml4PC1jYmluZChsaWJzb3JwaXhsPTEsbGlicy5tYXRyaXgpCmBgYAoKTmV4dCwgd2Ugd2lsbCByZWFkIGluIHRoZSBQSVhMIGRhdGEuIFdlIHdpbGwgcmVtb3ZlIHRoZSBhdG1vc3BoZXJpYyBzYW1wbGUgKGZpcnN0IHNhbXBsZSkgYW5kIG9ubHkgY2hvb3NlIG9uZSBvZiBlYWNoIFBJWEwgc2FtcGxlIGluIGFzIGVhY2ggYWJyYXNpb24gaGFzIHR3byBzYW1wbGVzIChvbmx5IG9uZSB3aWxsIGJlIG5lY2Vzc2FyeSBmb3IgdGhlIHBsb3QpLgoKYGBge3IsIGRhdGEwM30KI3JlYWQgaW4gcGl4bCBkYXRhIHdpdGggbGF0L2xvbmcKcGl4bC5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9TdHVkZW50RGF0YS9waXhsX3NvbF9jb29yZGluYXRlcy5SZHMiKQpwaXhsLmRmPC1waXhsLmRmICU+JQogIHNlbGVjdChjKDU6OCwxMjoxNCwxNywxOSwxOCwyMikpCiNyZW9yZGVyIHBpeGwgY29sdW1ucyBzbyB0aGF0IGl0IG1hdGNoZXMgbGlicyBkYXRhIG9yZ2FuaXphdGlvbgpwaXhsLmRmPC1waXhsLmRmWyxjKDExLDEwLDQsMyw4LDIsNiwxLDUsNyldCiNyZW1vdmUgYXRtb3NwaGVyaWMgc2FtcGxlCnBpeGwuZGY8LXBpeGwuZGZbMjoxNixdCnBpeGwuZGY8LWNiaW5kKGxpYnNvcnBpeGw9MCxwaXhsLmRmKQpgYGAKCkZpbmFsbHksIHdlIG1lcmdlIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cyB3ZSBoYXZlIG1vZGlmaWVkIHRodXMgZmFyIGZvciBhIGNvbWJpbmVkIExJQlMgYW5kIFBJWEwgZGF0YSBmcmFtZSBzdWl0YWJsZSBmb3IgYSBzb2lsIGNvbXBvc2l0aW9uIGxpbmUgcGxvdC4KYGBge3J9CmNvbG5hbWVzKHBpeGwuZGYpPC1jb2xuYW1lcyhsaWJzLm1hdHJpeCkKcGl4bGxpYnMuZGY8LXJiaW5kKHBpeGwuZGYsbGlicy5tYXRyaXgpCmBgYAoKIyMgNC4yIENvbnRyaWJ1dGlvbgoKU29tZSBvZiB0aGUgZGF0YSBtYW5pcHVsYXRpbmcgd29yayB3YXMgTWFyZ28ncywgc3VjaCBhcyB0aGUgZGlzdGFuY2UgZnVuY3Rpb24uIEluIHRlcm1zIG9mIHBpdm90aW5nIHRoZSBkYXRhIGZyYW1lIGFuZCB0aGUgb3RoZXIgc3RlcHMgb2YgdGhlIHByZXByb2Nlc3NpbmcgaXMgbXkgb3duIHdvcmsuIFRoZSBtYW5pcHVsYXRpbmcgYmVsb3cgdG8gcGxvdCB0aGUgbGluZSBzb2lsIGNvbXBvc2l0aW9uIHBsb3RzIGlzIG15IG93bi4KCiMjIDQuMyBNZXRob2RzIERlc2NyaXB0aW9uIAoKV2hlbiBkZWNpZGluZyBob3cgdG8gYXBwcm9hY2ggdGhlIGNvbmNlcHQgb2YgYnVpbGRpbmcgc29pbCBjb21wb3NpdGlvbiBwbG90cyBvZiBlYWNoIFBJWEwgYWJyYXNpb24gYW5kIHRoZSBjb3JyZXNwb25kaW5nIExJQlMgdGFyZ2V0cyB3aXRoaW4gYSBjZXJ0YWluIGRpc3RhbmNlIG1heGltdW0sIEkgZGVjaWRlZCB0aGUgYmVzdCB3YXkgd2FzIHRvIHN0YXJ0IHdpdGggdGhlIG9yaWdpbmFsIGRhdGEgc2V0cyBhbmQgbW9kaWZ5IHRoZW0gYXMgbmVlZGVkLiBGb3IgdGhlIGFjdHVhbCBwbG90LCB0aGUgYmVzdCB3YXkgdG8gZm9ybWF0IHRoZSBkYXRhIGNvcnJlY3RseSBpcyB0byBwaXZvdCBpdCwgYXMgSSBuZWVkIHRoZSB4IGF4aXMgdG8gYmUgdGhlIGNvbHVtbiBuYW1lcyBpbiB0aGUgY3VycmVudCBkYXRhIGZyYW1lIHdlIGhhdmUgKFNpTzIgYW5kIG90aGVyIGNvbXBvc2l0aW9ucykgYW5kIHRoZSB5IGF4aXMgdG8gYmUgdGhlIHdlaWdodGVkIGNvbXBvc2l0aW9uIHZhbHVlcy4gV2UgYWxzbyBuZWVkIGFuIGluZGljYXRvciBvZiBpZiB0aGUgZGF0YSBpcyBmcm9tIFBJWEwgb3IgTElCUywgd2hpY2ggYWxzbyBpcyBoZWxwZnVsIGZvciBidWlsZGluZyB0aGUgbGluZSBwbG90cy4gCgpVc2VycyB3aWxsIGhhdmUgdG8gc2V0IHRoZSBkaXN0YW5jZSB2YXJpYWJsZSBpbiBvcmRlciB0byBjaG9vc2UgdGhlIG1heCBkaXN0YW5jZSBiZXR3ZWVuIFBJWEwgYWJyYXNpb25zIGFuZCBMSUJTIHRhcmdldHMuIFRoaXMgY2FuIHZhc3RseSBjaGFuZ2UgdGhlIG51bWJlciBvZiBsaW5lcyBvbiB0aGUgcGxvdHMgd2hpY2ggY2FuIGhlbHAgcHJldmVudCBvdmVyY3Jvd2RlZCBwbG90cy4gVXNlcnMgYWxzbyBjYW4gc2V0IGEgdmFyaWFibGUgdG8gY2hvb3NlIGEgc3BlY2lmaWMgUElYTCBhYnJhc2lvbiBhbmQgY29ycmVzcG9uZGluZyBMSUJTIHRhcmdldHMsIHdoaWNoIGlzIGVhc2llciB0byBpbnRlcnByZXQgYXMgcGxvdHRpbmcgYWxsIG9mIHRoZSBMSUJTIGFuZCBQSVhMIGNvbXBvc2l0aW9uIGluZm9ybWF0aW9uIG9uIGxpbmUgcGxvdHMgbGVhZHMgdG8gdmVyeSBjb25kZW5zZWQgZ3JhcGhzIHRoYXQgYXJlIGhhcmQgdG8gcmVhZC4KCiMjIDQuNCBSZXN1bHQgYW5kIERpc2N1c3Npb24gCgpGaXJzdCwgd2Ugd2lsbCB0dXJuIHRoZSBlYXJ0aCBxdWFydGlsZSBpbmZvcm1hdGlvbiBpbnRvIGEgbG9uZyBkYXRhIGZyYW1lIChtZWFuaW5nIHBpdm90aW5nIHRoZSBjb2x1bW5zIGludG8gdGhlIHZhbHVlcykuIApgYGB7cn0KIyBFYXJ0aCBxdWFydGlsZXMKZWFydGhxdWFydGlsZXNfbG9uZyA8LSBlYXJ0aHF1YXJ0aWxlcy5kZiAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJTaU8yIik6bGFzdF9jb2woKSwgbmFtZXNfdG8gPSAiQ29tcG91bmQiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSIpCgplYXJ0aHF1YXJ0aWxlc19sb25nIDwtIGVhcnRocXVhcnRpbGVzX2xvbmcgJT4lIHJlbmFtZShRdWFydGlsZXMgPSBgVHJhaW5pbmcgc2V0IFF1YXJ0aWxlc2ApCmBgYAoKVGhlbiwgdGhlIGRhdGEgd2lsbCBiZSBmaWx0ZXJlZCB0byBvbmx5IGluY2x1ZGUgdGhlIGRhdGEgZnJvbSBhIHNwZWNpZmljIFBJWEwgYWJyYXNpb24gY2hvc2VuIGJ5IHRoZSB1c2VyLiBUaGUgZGF0YSBpcyBwaXZvdGVkIGludG8gYSBsb25nIGZvcm1hdCwgYW5kIHRoZSBjb2x1bW5zIGFyZSByZW9yZGVyZWQgdG8gbWltaWMgc2ltaWxhciBwbG90cyBmcm9tIE5BU0EgcGFwZXJzLgpgYGB7cn0KIyBGaWx0ZXIgZm9yIHRoZSBzcGVjaWZpYyBhYnJhc2lvbiBzYW1wbGUsIGUuZy4sICJBbGZhbGZhIgpwaXhsbGlic19maWx0ZXJlZCA8LSBwaXhsbGlicy5kZiAlPiUKICBmaWx0ZXIoQWJyYXNpb24gPT0gYWJyYXNpb25fbmFtZSkKCiMgUGl2b3QgdGhlIGRhdGEgdG8gbG9uZ2VyIGZvcm1hdCBmb3IgZ2dwbG90CnBpeGxsaWJzX2xvbmcgPC0gcGl4bGxpYnNfZmlsdGVyZWQgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiU2lPMiIpOmxhc3RfY29sKCksIG5hbWVzX3RvID0gIkNvbXBvdW5kIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2UiKQoKZGVzaXJlZF9vcmRlciA8LSBjKCJTaU8yIiwgIkFsMk8zIiwgIkZlT1QiLCAiTWdPIiwgIkNhTyIsICJOYTJPIiwgIksyTyIsICJUaU8yIikgICMgU3BlY2lmeSB5b3VyIGN1c3RvbSBvcmRlciBoZXJlCnBpeGxsaWJzX2xvbmckQ29tcG91bmQgPC0gZmFjdG9yKHBpeGxsaWJzX2xvbmckQ29tcG91bmQsIGxldmVscyA9IGRlc2lyZWRfb3JkZXIpCmBgYAoKRm9yIHRoZSBwbG90LCB3ZSB1c2UgZ2dwbG90IHRvIHBsb3QgdGhlIHBpeGxsaWJzX2xvbmcgZGF0YSBmcmFtZSB3ZSBjcmVhdGVkLiBUaGUgcGxvdCBpcyBjb2xvcmVkIGJ5IGlmIHRoZSBsaW5lIGlzIGEgUElYTCBhYnJhc2lvbidzIGNvbXBvc2l0aW9uIG9yIGEgTElCUyB0YXJnZXQncyBjb21wb3NpdGlvbi4gV2UgYWxzbyBhZGQgYSBsYXllciB3aXRoIHRoZSBlYXJ0aCBxdWFydGlsZSBpbmZvcm1hdGlvbiwgd2hpY2ggaXMgdGhlIGRvdHRlZCBsaW5lcy4KYGBge3J9CiMgTWFwIHRoZSBQSVhML0xJQlMgY29sdW1uIHRvIGNvbG9yIGFuZCB1c2UgdGFyZ2V0X25hbWUgdG8gZGlmZmVyZW50aWF0ZSBsaW5lcwpnZ3Bsb3QocGl4bGxpYnNfbG9uZywgYWVzKHggPSBDb21wb3VuZCwgeSA9IFBlcmNlbnRhZ2UsIGNvbG9yID0gYXMuZmFjdG9yKGxpYnNvcnBpeGwpLCBncm91cCA9IHRhcmdldCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogICMgQWRkIEVhcnRoIHF1YXJ0aWxlIGxpbmVzIHVzaW5nIGVhcnRocXVhcnRpbGVzX2xvbmcKICBnZW9tX2xpbmUoZGF0YSA9IGVhcnRocXVhcnRpbGVzX2xvbmcsIGFlcyh4ID0gQ29tcG91bmQsIHkgPSBQZXJjZW50YWdlLCBsaW5ldHlwZSA9IFF1YXJ0aWxlcywgZ3JvdXAgPSBRdWFydGlsZXMpLCAKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTb2lsIENvbXBvc2l0aW9uIGZvciBQSVhMIixhYnJhc2lvbl9uYW1lLCJhbmQgTElCUyB3aXRoaW4iLCBtZXRlcnMsICJtZXRlcnMiLCBzZXAgPSAiICIpLAogICAgICAgeCA9ICJDaGVtaWNhbCBDb21wb3VuZCIsCiAgICAgICB5ID0gIldlaWdodCBQZXJjZW50YWdlIiwKICAgICAgIGNvbG9yID0gIk1lYXN1cmVtZW50IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiRWFydGggUXVhcnRpbGVzIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIwIiA9ICJibHVlIiwgIjEiID0gInJlZCIpLCBsYWJlbHMgPSBjKCJQSVhMIiwgIkxJQlMiKSkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKSSBzdGlsbCBwbGFuIHRvIHVwZGF0ZSBhbmQgdHJ5IHVzaW5nIHRoZSBnZ3Bsb3RsYXkgZmVhdHVyZSB0byBpbmNvcnBvcmF0ZSBhbGwgdGhlIGFicmFzaW9ucyBhbmQgZGF0YSBvbnRvIG9uZSBncmlkIG9mIGxpbmUgcGxvdHMuIEkgYWxzbyBhbSBnb2luZyB0byBhZGQgcGxvdHMgd2hlcmUgdGhlIG1lYW4gaXMgdGFrZW4gb2YgYWxsIHRoZSBMSUJTIHRhcmdldHMgdGhhdCBjb3JyZXNwb25kIHRvIGEgUElYTCBhYnJhc2lvbiBzbyB0aGUgcGxvdCB3aWxsIG9ubHkgaGF2ZSBvbmUgTElCUyBsaW5lIGFuZCBvbmUgUElYTCBsaW5lIChhbG9uZyB3aXRoIHRoZSByZWZlcmVuY2VzKSwgdGhpcyBpcyBhbGwganVzdCBmb3IgdGhlIGRyYWZ0LiBJIGFsc28gbmVlZCB0byBvbmx5IGFkZCBjZXJ0YWluIHF1YXJ0aWxlIGluZm9ybWF0aW9uIGFuZCBsYWJlbCB0aGVtLCB0aGlzIGlzIGp1c3QgYSBwbGFjZWhvbGRlciBvZiB0aGUgcHJldmlvdXMgcGxvdC4gQWxzbyBtYXliZSB3aWxsIGFkZCBpbiBTQ0NUIHZhbHVlcyBhcyByZWZlcmVuY2VzLCBub3Qgc3VyZSBpZiB0aGV5IGFyZSBzdXBlciByZWxldmFudCBvciBob3cgdG8gc29ydCB0aGVtLgoKIyMgNC41IENvbmNsdXNpb25zIGFuZCBGdXR1cmUgV29yawpUaGlzIGZpbmRpbmcgY2FuIGJlIHVzZWQgYnkgZ2VvbG9naXN0cyB0byBhbmFseXplIHdoYXQgZGlmZmVyZW50IHNvaWwgY29tcG9zaXRpb25zIGFyb3VuZCBkaWZmZXJlbnQgUElYTCBhYnJhc2lvbnMgY2FuIG1lYW4gZm9yIGxpZmUgb24gTWFycy4gRm9yIGV4YW1wbGUsIG94aWRlIHByZXNlbmNlIGRvZXNuJ3QgbmVjZXNzYXJpbHkgaW5kaWNhdGUgbGlmZSwgYnV0IGl0IGNvdWxkIGluZGljYXRlIGJpb2xvZ2ljYWwgb3IgY2hlbWljYWwgbGlmZSBwcm9jZXNzZXMuIEZvciBleGFtcGxlLCBDYU8gY2FuIGluZGljYXRlIHRoZSBwcmVzZW5jZSBvZiBvbGQgYmlvbG9naWNhbCBtYXRlcmlhbCBsaWtlIHNoZWxscyBvciBmb3NzaWxzLgotQWRkIG1vcmUgYWJvdXQgZnV0dXJlIHdvcmssIG5vdCBzdXJlIHdoYXQgZWxzZSB0byBpbmNsdWRlCgojIDUuMCBGaW5kaW5nIDM6IEFuYWx5emluZyBDYXRpb24gQ29tYmluYXRpb25zIHVzaW5nIExJQlMgYW5kIFBJWEwgbWF0Y2hlZCBkYXRhClVzaW5nIHRoZSBMSUJTIGFuZCBQSVhMIGNvbWJpbmVkIGRhdGEgc2V0LCB3ZSBjcmVhdGVkIGEgdGVybmFyeSBwbG90IHRvIHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiBMSUJTIHNhbXBsZXMgc29ydGVkIGJ5IHdoYXQgUElYTCBhYnJhc2lvbiB0aGV5IGFyZSBjbG9zZXN0IHRvIChiYXNlZCBvbiBhIGNob3NlbiBkaXN0YW5jZSB2YXJpYWJsZSkuIE11Y2ggb2YgdGhlIGRhdGEgcHJlcHJvY2Vzc2luZyBpcyBzaW1pbGFyIHRvIEZpbmRpbmcgMSB3aGljaCB3ZSB3aWxsIHJlcGVhdCBoZXJlLiBIb3dldmVyLCB0aGUgZ29hbCBoZXJlIGlzIHRvIGFuYWx5emUgaG93IGRpZmZlcmVudCBncm91cHMgb2YgTElCUyBzYW1wbGVzIChjb2xvcmVkIGJ5IG1hdGNoaW5nIFBJWEwgYWJyYXNpb24pIGRpZmZlciBieSBjYXRpb24gY29tcG9zaXRpb24uCgojIyA1LjEgRGF0YSwgQ29kZSwgYW5kIFJlc291cmNlcwpIZXJlIGlzIGEgbGlzdCBkYXRhIHNldHMsIGNvZGVzLCB0aGF0IGFyZSB1c2VkIGluIHlvdXIgd29yay4gQWxvbmcgd2l0aCBicmllZiBkZXNjcmlwdGlvbiBhbmQgVVJMIHdoZXJlIHRoZXkgYXJlIGxvY2F0ZWQuCgoxLiBwZXRlcmMtZmluYWxQcm9qZWN0RjI0LlJtZCAod2l0aCBrbml0IHBkZiBhbmQgaHRtbCkgaXMgdGhpcyBub3RlYm9vay4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnROb3RlYm9va3MvQXNzaWdubWVudDA3X0RyYWZ0RmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNF9yb3VnaGRyYWZ0LlJtZF0oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDdfRHJhZnRGaW5hbFByb2plY3ROb3RlYm9vay9wZXRlcmNfZmluYWxQcm9qZWN0RjI0X3JvdWdoZHJhZnQuUm1kKQoKMi4gc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcyB3aGljaCBpcyB0aGUgb3JpZ2luYWwgTElCUyBkYXRhIGdpdmVuIHRvIG91ciByZXNlYXJjaCBncm91cC4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkc10oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vRGF0YS9zdXBlcmNhbV9saWJzX21vY19sb2MuUmRzKQoKCkZpcnN0LCB3ZSBzZXQgYSBkaXN0YW5jZSB2YXJpYWJsZSB3aGljaCBjYW4gYmUgdXNlZCBhcyBhIHNsaWRlciBiYXIgaW4gdGhlIGFwcC4gQ2hhbmdpbmcgdGhpcyB2YXJpYWJsZSBzZXRzIHRoZSBtYXhpbXVtIGRpc3RhbmNlIGJldHdlZW4gYSBQSVhMIHRhcmdldCBhbmQgTElCUyBzYW1wbGUgZm9yIHRoZW0gdG8gYmUgY2xhc3NpZmllZCB0b2dldGhlci4KYGBge3J9CiNzZXQgZGlzdGFuY2UgdmFyaWFibGUgd2hpY2ggY2FuIGJlIHVzZWQgYXMgYSB0b2dnbGUgdG9vbApkaXN0YW5jZT03CmBgYAoKVG8gcHJlcGFyZSB0aGUgZGF0YSwgSSBzdGFydCBieSBsb2FkaW5nIGluIHRoZSBMSUJTIGRhdGEuIFRoZW4sIHdlIGRyb3AgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBjb2x1bW5zIGFuZCBzdW0gb2YgcGVyY2VudGFnZSBjb2x1bW5zIGxlYXZpbmcgdXMgd2l0aCBqdXN0IHRoZSB3ZWlnaHRlZCBjb21wb3NpdGlvbiBpbiB0ZXJtcyBvZiBudW1lcmljYWwgZGF0YS4gV2UgYWxzbyByZW1vdmUgdGhlIHNjY3QgdmFsdWVzLCBhcyB0aG9zZSB2YWx1ZXMgYXJlIHRoZSBvbmVzIHRoYXQgYXJlIGVhcnRoIHJlZmVyZW5jZSBzYW1wbGVzIHRoYXQgUGVyc2VydmVyYW5jZSBjYXJyaWVzIHdpdGggaXQuIFRoZXJlZm9yZSwgdGhleSB3aWxsIG5vdCBiZSB2ZXJ5IHJlbGV2YW50IHdoZW4gcGxvdHRpbmcgdGhlIExJQlMgZGF0YSBhcyB3ZSBhcmUgZm9jdXNlZCBvbiB0aGUgY2F0aW9uIGNvbWJpbmF0aW9ucyBhbmQgdGhlcmVmb3JlIG9ubHkgbmVlZCB0aGUgd2VpZ2h0ZWQgY29tcG9zaXRpb25zLgpgYGB7cn0KI0xvYWQgaW4gTElCUyBkYXRhCmxpYnMuZGYgPC0gcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9EYXRhL3N1cGVyY2FtX2xpYnNfbW9jX2xvYy5SZHMiKQojRHJvcCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGZlYXR1cmVzLCB0aGUgc3VtIG9mIHRoZSBwZXJjZW50YWdlcywgCiN0aGUgZGlzdGFuY2UsIGFuZCB0aGUgdG90YWwgZnJlcXVlbmNpZXMKbGlicy5kZiA8LSBsaWJzLmRmICU+JSAKICBzZWxlY3QoIShjKGRpc3RhbmNlX21tLFRvdC5FbS4sU2lPMl9zdGRldixUaU8yX3N0ZGV2LEFsMk8zX3N0ZGV2LEZlT1Rfc3RkZXYsCiAgICAgICAgICAgICBNZ09fc3RkZXYsTmEyT19zdGRldixDYU9fc3RkZXYsSzJPX3N0ZGV2LFRvdGFsKSkpCiMgQ29udmVydCB0aGUgcG9pbnRzIHRvIG51bWVyaWMKbGlicy5kZiRwb2ludCA8LSBhcy5udW1lcmljKGxpYnMuZGYkcG9pbnQpCmxpYnMuZGZbLDY6MTNdIDwtIHNhcHBseShsaWJzLmRmWyw2OjEzXSxhcy5udW1lcmljKQojcmVtb3ZlIHRoZSBzY2N0L3JlZmVyZW5jZSBzYW1wbGVzCmxpYnMuZGY8LWxpYnMuZGYlPiUKICBmaWx0ZXIoIShncmVwbCgic2NjdCIsIHRhcmdldCkpKQojYWRkIGEgY29sdW1uIHRvIGluZGljYXRlIHRoZSBuZWFyZXN0IHBpeGwKbGlicy5kZjwtY2JpbmQobmVhcmVzdHBpeGw9MCxsaWJzLmRmKQojbWFrZSBhIGRhdGFmcmFtZSBvZiBqdXN0IHRoZSBMSUJTIExhdC9Mb25nIGFuZCB0YXJnZXQgbmFtZSBhbmQgcmVtb3ZlIGR1cGxpY2F0ZXMKbGlic3RhcmdldHMuZGY8LWxpYnMuZGZbLGMoMSwzLDQsNSldCmxpYnN0YXJnZXRzLmRmPC1kaXN0aW5jdChsaWJzdGFyZ2V0cy5kZikKYGBgCgpMb2FkIGluIFBJWEwgZGF0YQpgYGB7cn0KI3JlYWQgaW4gcGl4bCBkYXRhIHdpdGggbGF0L2xvbmcKcGl4bC5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9TdHVkZW50RGF0YS9waXhsX3NvbF9jb29yZGluYXRlcy5SZHMiKQojaW5jbHVkZSBvbmx5IHBpeGwgbWV0YWRhdGEKcGl4bC5kZjwtcGl4bC5kZiAlPiUKICBzZWxlY3QoYygxLDIsMTksMjAsMjIpKQojY29udmVydCBMYXQvTG9uZyB0byBudW1lcmljCnBpeGwuZGYkTGF0IDwtIGFzLm51bWVyaWMocGl4bC5kZiRMYXQpCnBpeGwuZGYkTG9uZyA8LSBhcy5udW1lcmljKHBpeGwuZGYkTG9uZykKI3JlbW92ZSByb3dzIHNvIHdlIG9ubHkgaGF2ZSBvbmUgc2FtcGxlIHBlciBhYnJhc2lvbiBhbmQgcmVtb3ZlIGF0bW9zcGhlcmljIHNhbXBsZQpwaXhsLmRmPC1waXhsLmRmW2MoMiw0LDYsOCwxMCwxMiwxNCwxNiksXQpgYGAKCk5leHQsIHdlIHdpbGwgaW5pdGlhbGl6ZSBhIGRpc3RhbmNlIHZhcmlhYmxlICh0byBpbmRpY2F0ZSBkaXN0YW5jZSBiZXR3ZWVuIFBJWEwgYWJyYXNpb24gYW5kIExJQlMgdGFyZ2V0KSBhbmQgYWxzbyBpbml0aWFsaXplIGVhY2ggUElYTCBhYnJhc2lvbiwgd2hpY2ggd2lsbCBiZSB1c2VkIHRvIG1hcmsgd2hpY2ggUElYTCBhYnJhc2lvbiB0aGUgTElCUyBzYW1wbGUgaXMgY2xvc2VzdCB0byBieSB1c2luZyBhIGZhY3RvciBvZiAwIG9yIDEuIApgYGB7cn0KI0xJQlMgdGFyZ2V0IGRhdGEgZnJhbWUgd2l0aCBkaXN0YW5jZSB2YXJpYWJsZSBhcyB3ZWxsCmxpYnN0YXJnZXRzLmRmPC1jYmluZChsaWJzdGFyZ2V0cy5kZiwiRGlzdGFuY2UiPTAsIkJlbGxlZ3JhZGUiPTAsIkRvdXJiZXMiPTAsIlF1YXJ0aWVyIj0wLCJBbGZhbGZhIj0wLCJUaG9ybnRvbkdhcCI9MCwiQmVycnlIb2xsb3ciPTAsIk5vdmFydXB0YSI9MCwiVWdhbmlrSXNsYW5kIj0wKQpgYGAKClRoZSBkaXN0YW5jZSBmdW5jdGlvbiBiZWxvdyB3aWxsIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIExJQlMgdGFyZ2V0IGFuZCBhbGwgdGhlIFBJWEwgYWJyYXNpb25zLCBhbmQgcGljayB0aGUgc21hbGxlc3QgZGlzdGFuY2UgdG8gcGljayB0aGUgY2xvc2VzdCBQSVhMIGFicmFzaW9uIHRvIHRoYXQgTElCUyB0YXJnZXQuCmBgYHtyfQojRGlzdGFuY2UgZnVuY3Rpb24KZm9yKGkgaW4gMTpucm93KGxpYnN0YXJnZXRzLmRmKSkgewogICAgbGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXTwtYyhkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbOCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpKQogICAgCiAgICBsaWJzdGFyZ2V0cy5kZltpLDFdPC13aGljaC5taW4obGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXSkKICAgIGxpYnN0YXJnZXRzLmRmW2ksNV08LW1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQp9CmxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPC1hcy5mYWN0b3IobGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGwpCmxldmVscyhsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCk8LShjKCJCZWxsZWdyYWRlIiwiRG91cmJlcyIsIlF1YXJ0aWVyIiwiQWxmYWxmYSIsIlRob3JudG9uR2FwIiwiQmVycnlIb2xsb3ciLCJOb3ZhcnVwdGEiLCJVZ2FuaWtJc2xhbmQiKSkKYGBgCgpCZWxvdyBpcyBhbm90aGVyIGluaXRpYWxpemVyIGZvciB0aGUgUElYTCBhYnJhc2lvbiBkYXRhLiBUaGlzIHNldHMgdGhlIHZhcmlhYmxlcyBmb3IgZWFjaCBQSVhMIGFicmFzaW9uLgpgYGB7cn0KI1NldHMgZWFjaCBuZWFyZXN0IFBJWEwgdmFyaWFibGUgZm9yIGZ1dHVyZSB1c2UgaW4gZGVjaWRpbmcgd2hpY2ggdGFyZ2V0IGlzIGNsb3Nlc3QgdG8gYSBMSUJTIHNhbXBsZQpCZWxsZWdyYWRlPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlbGxlZ3JhZGUiLF0kdGFyZ2V0CkRvdXJiZXM8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iRG91cmJlcyIsXSR0YXJnZXQKUXVhcnRpZXI8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iUXVhcnRpZXIiLF0kdGFyZ2V0CkFsZmFsZmE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQWxmYWxmYSIsXSR0YXJnZXQKVGhvcm50b25HYXA8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVGhvcm50b25HYXAiLF0kdGFyZ2V0CkJlcnJ5SG9sbG93PC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlcnJ5SG9sbG93IixdJHRhcmdldApOb3ZhcnVwdGE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iTm92YXJ1cHRhIixdJHRhcmdldApVZ2FuaWtJc2xhbmQ8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVWdhbmlrSXNsYW5kIixdJHRhcmdldApgYGAKCk5leHQsIHdlIGZpbHRlciBvdXQgdGhlIExJQlMgdGFyZ2V0cyB0aGF0IGFyZSBub3Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgZGlzdGFuY2UgdmFyaWFibGUuIFRoZW4sIHdlIG1lcmdlIHRoZSBMSUJTIGRhdGEgd2l0aCB0aGUgcmVzcGVjdGl2ZSBQSVhMIGFicmFzaW9uIGJ5IG11dGF0aW5nIGFuZCBhZGRpbmcgYW4gYWJyYXNpb24gY29sdW1uIHRoYXQgaGFzIHRoZSBhYnJhc2lvbiBuYW1lIGNsb3Nlc3QgdG8gZWFjaCBMSUJTIHRhcmdldC4gV2UgYWxzbyBhZGQgYSBjb2x1bW4sIExJQlMgb3IgUElYTCwgd2hpY2ggZGVub3RlcyBpZiB0aGUgcm93IG9mIGRhdGEgaXMgZnJvbSB0aGUgUElYTCBhbmQgTElCUyBkYXRhIHNldHMuIFdlIGFsc28gc2V0IHVwIHRoZSBsaWJzLnRlcm4gbWF0cml4IHdoaWNoIHdpbGwgCmBgYHtyfQppbmNsdWRlZC5saWJzPC0obGlic3RhcmdldHMuZGYlPiUKICBmaWx0ZXIoRGlzdGFuY2U8bWV0ZXJzKSkkdGFyZ2V0CmxpYnMubWF0cml4IDwtbGlicy5kZiAlPiUKICBmaWx0ZXIodGFyZ2V0ICVpbiUgaW5jbHVkZWQubGlicykKI3NldCBMSUJTIG1hdHJpeCBhbmQgdGVybmFyeSBwbG90IGJ5IGFkZGluZyBpbiBjYXRpb24gY29tcG9uZW50cyBhbmQgbXV0YXRpbmcKbGlicy5tYXRyaXggPC0gbGlicy5tYXRyaXhbLGMoNSw3OjE0KV0KbGlicy50ZXJuIDwtIGFzLmRhdGEuZnJhbWUobGlicy5tYXRyaXgpICU+JQogIG11dGF0ZSh4PShTaU8yK0FsMk8zKS8xMDAseT0oRmVPVCtNZ08pLzEwMCx6PShDYU8rTmEyTytLMk8pLzEwMCkgJT4lCiAgc2VsZWN0KC1jKFNpTzIsQWwyTzMsRmVPVCxNZ08sQ2FPLE5hMk8sSzJPLFRpTzIpKQpsaWJzLnRlcm48LWNiaW5kKCJBYnJhc2lvbiI9MCxsaWJzLnRlcm4pCiNTZXQgd2hhdCBhYnJhc2lvbiBnb2VzIHdpdGggdGhlIHJlc3BlY3RpdmUgTElCUyBzYW1wbGUgaXQgbWF0Y2hlcyB3aXRoCmxpYnMudGVybjwtbGlicy50ZXJuJT4lCiAgbXV0YXRlKEFicmFzaW9uID0gaWZlbHNlKHRhcmdldCVpbiVBbGZhbGZhLCJBbGZhbGZhIiwgCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIEJlbGxlZ3JhZGUsICJCZWxlZ3JhZGUiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBCZXJyeUhvbGxvdywgIkJlcnJ5SG9sbG93IiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgRG91cmJlcywgIkRvdXJiZXMiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBOb3ZhcnVwdGEsICJOb3ZhcnVwdGEiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBRdWFydGllciwgIlF1YXJ0aWVyIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgVGhvcm50b25HYXAsICJUaG9ybnRvbkdhcCIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFVnYW5pa0lzbGFuZCwgIlVnYW5pa0lzbGFuZCIsQWJyYXNpb24pKSkpKSkpKSkKI3N1bW1hcnkgb2YgTElCUyBkYXRhIGluY2x1ZGluZyBkaXN0YW5jZSBwYXJhbWV0ZXIsIG51bWJlciBvZiBMSUJTIHRhcmdldHMsIGFuZCBudW1iZXIgb2YgTElCUyBwb2ludHMKa2FibGVkZjwtcmJpbmQoIkRpc3RhbmNlIChtKSI9bWV0ZXJzLCJUYXJnZXRzIj1sZW5ndGgoaW5jbHVkZWQubGlicyksIlBvaW50cyI9bnJvdyhsaWJzLnRlcm4pKQprYWJsZShrYWJsZWRmLCBjYXB0aW9uID0iTElCUyAjIG9mIFRhcmdldHMgYW5kIFBvaW50cyB3aXRoaW4gU3BlY2lmaWVkIERpc3RhbmNlIikKYGBgCk5leHQsIHdlIHdpbGwgc2V0IHVwIGEgdGVybmFyeSBkYXRhIGZyYW1lIGZvciB0aGUgUElYTCBkYXRhIHRvIGFkZCBzb21lIHJlZmVyZW5jZSBwb2ludHMgb24gdG9wIG9mIHRoZSBMSUJTIGRhdGEuIFRoaXMgc2hvdWxkIHByb3ZpZGUgbW9yZSBpbnNpZ2h0IGludG8gaG93IHRoZSBjb21wb3NpdGlvbiBvZiBQSVhMIGFuZCBMSUJTIHNhbXBsZXMgcmVsYXRlIGJ5IHRoZWlyIGNhdGlvbiBjb21iaW5hdGlvbnMKCmBgYHtyfQojIFBJWEwgZGF0YSBhZGRlZApwaXhsLmRmIDwtIHJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvRGF0YS9zYW1wbGVzX3BpeGxfd2lkZS5SZHMiKQpwaXhsLmRmW3NhcHBseShwaXhsLmRmLCBpcy5jaGFyYWN0ZXIpXSA8LSBsYXBwbHkocGl4bC5kZltzYXBwbHkocGl4bC5kZiwgaXMuY2hhcmFjdGVyKV0sCmFzLmZhY3RvcikKcGl4bC5kZiA8LSBwaXhsLmRmWzI6MTYsXSAjRXhjbHVkaW5nIGZpcnN0LCBhdG1vc3BoZXJpYyBzYW1wbGUKI1BJWEwgZGF0YSwgd2l0aCBpZGVudGljYWxseSByZWZsZWN0ZWQgY29tcG9zaXRpb25zCm5ld19waXhsX3RyaW0gPC0gcGl4bC5kZiAlPiUKZHBseXI6OnNlbGVjdChjKCJOYTIwIiwiTWdvIiwiQWwyMDMiLCJTaTAyIiwgIksyMCIsIkNhbyIsIkZlTy1UIiwgY2FtcGFpZ24sIHR5cGUpKSAlPiUKcmVuYW1lKCJOYTJPIj0iTmEyMCIsIk1nTyI9Ik1nbyIsIkFsMk8zIj0iQWwyMDMiLCJTaU8yIj0iU2kwMiIsIksyTyI9IksyMCIsCiJDYU8iPSJDYW8iLCJGZU9UIj0iRmVPLVQiKQojdGFrZSB0aGUgc3VtcyBvZiB0aGUgc3BlY2lmaWMgZWxlbWVudHMsIGFuZCByZW5hbWUgdHlwZSBjb2x1bW4KcGl4bF90ZXJuYXJ5IDwtIG5ld19waXhsX3RyaW0gJT4lCm11dGF0ZSh4PShTaU8yK0FsMk8zKS8xMDAseT0oRmVPVCtNZ08pLzEwMCx6PShDYU8rTmEyTytLMk8pLzEwMCwgUElYTF9Sb2NrX1R5cGUgPSB0eXBlKSAlPiUKc2VsZWN0KC1jKFNpTzIsQWwyTzMsRmVPVCxNZ08sQ2FPLE5hMk8sSzJPKSkgJT4lCmRyb3BfbmEoKQojVGhpcyBpcyBmb3IgdGhlIGxhYmVscyBvbiB0aGUgVGVybmFyeSBQbG90IGJlbG93CnBpeGxfdGVybmFyeSA8LSBjYmluZChwaXhsX3Rlcm5hcnksIFNhbXBsZV9kaXNwbGF5PQpjKCIyIiwiMyIsIjQsNiw3IiwiNSw4LDkiLCIiLCIiLCIiLCIiLAoiMTAsMTEiLCIiLCIxMiwxMyIsIiIsIjE0LDE1IiwiIiwiMTYiKSkKYGBgCgoKCiMjIDUuMiBDb250cmlidXRpb24KClRoaXMgd29yayB3YXMgYWxzbyBhIGNvbWJpbmF0aW9uIG9mIG1lIGFuZCBNYXJnby4gVGhlIGRhdGEgc2V0IGNyZWF0aW9uIHdhcyBib3RoIG9mIHVzIGluIG91ciBicmFpbnN0b3JtaW5nIGFzIHRoaXMgdXRpbGl6ZXMgdGhlIGRhdGEgc2V0IHdlIGNyZWF0ZWQgb2YgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBmb3IgUElYTC4KLSBBZGQgbW9yZSBoZXJlCi0gVmVyeSBzaW1pbGFyIHRvIG90aGVyIHR3byBzZWN0aW9ucyBhZGQgaW4gbGF0ZXIsIE1hcmdvIGFuZCBJIHdvcmtlZCBvbiBtb3N0IG9mIHRoaXMgdG9nZXRoZXIKCiMjIDUuMyBNZXRob2RzIERlc2NyaXB0aW9uIAoKLSBTdGFydGVkIHdpdGggZmlsdGVyaW5nIG9yaWdpbmFsIGRhdGEgdG8gZ2V0IHJpZCBvZiBTQ0NUIHZhbHVlcwotIHRoZW4gc2V0IHVwIHRlcm5hcnkgZGF0YSBmcmFtZSBieSBtdXRhdGluZyBieSBjYXRpb24gY29tcG9zaXRpb25zCi0gdGhlbiBtdXRhdGVkIHRvIG1ha2UgdGhlIFBJWEwgYWJyYXNpb25zIHRoZSBrZXksIHNvIHRoZSBMSUJTIHRhcmdldHMgYXJlIGNvbG9yZWQgYnkgdGhlIGNsb3Nlc3QgUElYTCBhYnJhc2lvbiwgY3JlYXRpbmcgYSBmb3JtIG9mIGNsdXN0ZXJzLgoKIyMgNS40IFJlc3VsdCBhbmQgRGlzY3Vzc2lvbiAKVXNpbmcgYWxsIG9mIHRoZSBtYW5pcHVsYXRpb24gZG9uZSBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSB0ZXJuYXJ5IHBsb3QsIHdlIHRoZW4gcGxvdCB1c2luZyB0aGUgZ2d0ZXJuIGNvbW1hbmQuIFdlIHdpbGwgY29sb3IgYnkgYWJyYXNpb24gdG8gc2VlIHRoZSBkaXN0cmlidXRpb24gb2YgY29tcG9zaXRpb24gYmV0d2VlbiBkaWZmZXJlbnQgYWJyYXNpb25zLiBUaGlzIHNob3VsZCBoZWxwIHVzIGJlIGFibGUgdG8gZHJhdyBkaWZmZXJlbnQgY29uY2x1c2lvbnMgYWJvdXQgaG93IGFicmFzaW9ucyByZWxhdGUgb3IgZG9uJ3QgcmVsYXRlLiBUaGUgbWF4IGRpc3RhbmNlIGJldHdlZW4gdGhlIFBJWEwgdGFyZ2V0IGFuZCBMSUJTIHNhbXBsZSBjYW4gYmUgbW9kaWZpZWQgaG93ZXZlciBkZXNpcmVkLgpgYGB7cn0KZ2d0ZXJuKGxpYnMudGVybiwgZ2d0ZXJuOjphZXMoeD14LHk9eSx6PXopKSArCiAgZ2VvbV9wb2ludChkYXRhPWxpYnMudGVybixhZXMoY29sb3I9QWJyYXNpb24sYWxwaGE9MC41KSkgKyAKICB0aGVtZV9yZ2J3KCkgKyAKICBsYWJzKHRpdGxlPXBhc3RlKCJNYXJzIExJQlMgRGF0YSBXaXRoaW4iLGRpc3RhbmNlLCJtZXRlcnMgb2YgUElYTCIsc2VwPSIgIiksCiAgICAgICB4PSJTaStBbCIsCiAgICAgICB5PSJGZStNZyIsCiAgICAgICB6PSJDYStOYStLIiwKICAgICAgIGNhcHRpb24gPSAiTElCUyBzYW1wbGVzIHRoYXQgYXJlIHdpdGhpbiA3IG1ldGVycyBvZiBhIFBJWEwgYWJyYXNpb24uIFxuRWFjaCBMSUJTIHNhbXBsZSBpcyBjb2xvcmVkIGJ5IHdoYXQgUElYTCBhYnJhc2lvbiBpdCBtYXRjaGVzIHdpdGguIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIsCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSAgIyBBbGlnbnMgY2FwdGlvbiB0byB0aGUgbGVmdAogICkgKyAKICBndWlkZXMoYWxwaGE9Im5vbmUiKSsKICBzdXBwcmVzc1dhcm5pbmdzKGdlb21fcG9pbnQoCiAgICBkYXRhPXBpeGxfdGVybmFyeSwgZ2d0ZXJuOjphZXMoY2x1c3Rlcj1QSVhMX1JvY2tfVHlwZSwgc2hhcGU9UElYTF9Sb2NrX1R5cGUpLCBzaXplID0gMikpICsKI0FkZCBsYWJlbHMgdG8gUElYTCBkYXRhIGNvcnJlc3BvbmRpbmcgdG8gc2FtcGxlIG51bWJlcgogIHN1cHByZXNzV2FybmluZ3MoZ2VvbV90ZXh0KGRhdGE9cGl4bF90ZXJuYXJ5LCBnZ3Rlcm46OmFlcyh4PXgsIHk9eSwgej16LCBsYWJlbD1TYW1wbGVfZGlzcGxheSwgY2x1c3Rlcj1QSVhMX1JvY2tfVHlwZSwgICMgSG9yaXpvbnRhbCBhZGp1c3QgdG8gYXZvaWQgb3ZlcmxhcAogICAgaGp1c3QgPSBpZmVsc2UoeCA+IDAuNDMsIDEsIC0wLjEpLAogICAgdmp1c3QgPSBpZmVsc2UoeCA9PSAwLjM2NjgsIDEuMywKICAgICAgICBpZmVsc2UoeCA9PSAwLjM3NSwgMSwgaWZlbHNlKHggPiAwLjQzLCAxLjUsIC0wLjMpKSksCiAgICBmb250ZmFjZT0iYm9sZCIpLAogICAgc2l6ZT0yLjcpKQpgYGAKCiMjIDUuNSBDb25jbHVzaW9ucyBhbmQgRnV0dXJlIFdvcmsKQmFzZWQgb24gdGhpcyB0ZXJuYXJ5IHBsb3QsIHdlIGNhbiBzZWUgQWxmYWxmYSBhbmQgQmVsZWdyYWRlIGFyZSBoaWdoZXIgaW4gU2krQWwgYW5kIFVnYW5payBJc2xhbmQgaXMgYW4gb3V0bGllci4gQXMgdGhpcyB3YXMgdGhlIGxhc3QgcGllY2Ugb2YgdGhlIFBJWEwgZGF0YSBpbiB0aGUgZGF0YSBzZXQgYW5kIGl0IHdhcyBtaXNzaW5nIGEgcGFpciBzaW5jZSBldmVyeSBvdGhlciBhYnJhc2lvbiB3YXMgbWFkZSB1cCBvZiB0d28gc2FtcGxlcywgaXQgaXMgaW5jbHVkZWQgaW4gaGVyZSBidXQgdW50aWwgdGhlIGRhdGEgc2V0IGlzIHVwZGF0ZWQgdGhlcmUgaXMgbm90IGVub3VnaCBjb250ZXh0IHRvIGV4cGxhaW4gd2h5IGl0IGlzIHNvIHZhc3RseSBkaWZmZXJlbnQuIEkgd291bGQgYXNzdW1lIGl0IGlzIGR1ZSB0byBob3cgdGhlIHJvYm90IGlzIHRyYXZlbGluZyBhbmQgdGhlIGxvY2F0aW9uIG9mIHRoZSBVZ2FuaWtJc2xhbmQgYWJyYXNpb24gaXMgdmVyeSBkaWZmZXJlbnQgdGhhbiB0aGUgb3RoZXIgNyBhYnJhc2lvbnMuCi0gRnV0dXJlIHdvcmssIHdvdWxkIGluY2x1ZGUgbW9yZSBkYXRhIHRvIGdhaW4gYnJvYWRlciBjb250ZXh0CgojIEJpYmxpb2dyYXBoeQpQcm92aWRlIGEgbGlzdGluZyBvZiByZWZlcmVuY2VzIGFuZCBvdGhlciBzb3VyY2VzLgoKKiBBbmFseXN0J3MgTm90ZWJvb2sKKiBOb3Qgc3VyZSB3aGF0IGVsc2UgaXMgcmVsZXZhbnQsIG1vc3Qgb2Ygd2hhdCBJIHVzZWQgd2FzIHNpbWlsYXIgdG8gQW5hbHlzdCdzIE5vdGVib29rCgojIEFwcGVuZGl4CgoqSW5jbHVkZSBoZXJlIHdoYXRldmVyIHlvdSB0aGluayBpcyByZWxldmFudCB0byBzdXBwb3J0IHRoZSBtYWluIGNvbnRlbnQgb2YgeW91ciBub3RlYm9vay4gRm9yIGV4YW1wbGUsIHlvdSBtYXkgaGF2ZSBvbmx5IGluY2x1ZGUgZXhhbXBsZSBmaWd1cmVzIGFib3ZlIGluIHlvdXIgbWFpbiB0ZXh0IGJ1dCBpbmNsdWRlIGFkZGl0aW9uYWwgb25lcyBoZXJlLiBPciB5b3UgbWF5IGhhdmUgZG9uZSBhIG1vcmUgZXh0ZW5zaXZlIGludmVzdGlnYXRpb24sIGFuZCB3YW50IHRvIHB1dCBtb3JlIHJlc3VsdHMgaGVyZSB0byBkb2N1bWVudCB5b3VyIHdvcmsgaW4gdGhlIHNlbWVzdGVyLiBCZSBzdXJlIHRvIGRpdmlkZSBhcHBlbmRpeCBpbnRvIGFwcHJvcHJpYXRlIHNlY3Rpb25zIGFuZCBtYWtlIHRoZSBjb250ZW50cyBjbGVhciB0byB0aGUgcmVhZGVyIHVzaW5nIGFwcHJvYWNoZXMgZGlzY3Vzc2VkIGFib3ZlLiAqIApTaG91bGQgSSBhZGQgbW9yZSBleGFtcGxlcyBoZXJlIG9mIHNvaWwgY29tcG9zaXRpb24gcGxvdHMgb2YgZGlmZmVyZW50IGFicmFzaW9ucz8gSSBhbHNvIGNvdWxkIGFkZCBoZWF0IG1hcCBhbmFseXNpcyB0byB0aGlzIG5vdGVib29rIGFzIGEgZmluZGluZyBidXQgd2Fzbid0IHN1cmUgaWYgaXQgd2FzIHJlYWxseSByZWxldmFudC4KCg==
+
LS0tCnRpdGxlOiAiRGF0YSBBbmFseXRpY3MgUmVzZWFyY2ggSW5kaXZpZHVhbCBGaW5hbCBQcm9qZWN0IFJlcG9ydCAtIE1hcnMiCmF1dGhvcjogIkNoYXJsb3R0ZSBQZXRlcnNvbiIKZGF0ZTogIkZhbGwgMjAyNCIKb3V0cHV0OgogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICczJwogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogdW5pdGVkCi0tLQoKCiMgREFSIFByb2plY3QgYW5kIEdyb3VwIE1lbWJlcnMKCiogUHJvamVjdCBuYW1lOiBNYXJzCiogR2l0SHViIElEOiBkYXItcGV0ZXJjCiogUHJvamVjdCB0ZWFtIG1lbWJlcnM6IERhbnRlIE13YXRpYm8sIERvw7FhIFJvYmVydHMsIERhdmlkIFdhbGN5emssIFh1YW50aW5nIFdhbmcsIEFzaHRvbiBDb21wdG9uLCBNYXJnbyBWYW5Fc3NlbHN0eW4sIE5pY29sYXMgTW9yYXdza2ksIENKIE1hcmlubywgQWFkaSBMYWhpcmkgCgojIDAuMCBQcmVsaW1pbmFyaWVzLgoKYGBge3J9CiMgU2V0IHRvIFRSVUUgdG8gZXhwYW5kIFIgY29kZSBibG9ja3M7IHNldCB0byBGQUxTRSB0byBjb2xsYXBzZSBSIGNvZGUgYmxvY2tzIApzaG93IDwtIFRSVUUKYGBgCgpFeGVjdXRpbmcgdGhpcyBSIG5vdGVib29rIHJlcXVpcmVzIHNvbWUgc3Vic2V0IG9mIHRoZSBmb2xsb3dpbmcgcGFja2FnZXM6CgoqIGBnZ3Bsb3QyYAoqIGB0aWR5dmVyc2VgCiogYHBhbmRvY2AKKiBgcm1hcmtkb3duYAoqIGBzdHJpbmdyYAoqIGBnZ2JpcGxvdGAKKiBga25pdHJgCiogYHJwYXJ0YAoqIGBycGFydC5wbG90YAoqIGBjYXJldGAKKiBgZ2dyZXBlbGAKKiBgZ2d0ZXJuYAoqIGBnZW9zcGhlcmVgCgoKVGhlc2Ugd2lsbCBiZSBpbnN0YWxsZWQgYW5kIGxvYWRlZCBhcyBuZWNlc3NhcnkgKGNvZGUgc3VwcHJlc3NlZCkuIAoKPCEtLSBUaGUgYGluY2x1ZGU9RkFMU0VgIG9wdGlvbiBwcmV2ZW50cyB5b3VyIGNvZGUgZnJvbSBiZWluZyBzaG93biBhdCBhbGwgLS0+CmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIFRoaXMgY29kZSB3aWxsIGluc3RhbGwgcmVxdWlyZWQgcGFja2FnZXMgaWYgdGhleSBhcmUgbm90IGFscmVhZHkgaW5zdGFsbGVkCiMgQUxXQVlTIElOU1RBTEwgWU9VUiBQQUNLQUdFUyBMSUtFIFRISVMhCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQogICBsaWJyYXJ5KGdncGxvdDIpCn0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkKfQoKaWYgKCFyZXF1aXJlKCJwYW5kb2MiKSkgewogIGluc3RhbGwucGFja2FnZXMoInBhbmRvYyIpCiAgbGlicmFyeShwYW5kb2MpCn0KCiMgUmVxdWlyZWQgcGFja2FnZXMgZm9yIE0yMCBMSUJTIGFuYWx5c2lzCmlmICghcmVxdWlyZSgicm1hcmtkb3duIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJybWFya2Rvd24iKQogIGxpYnJhcnkocm1hcmtkb3duKQp9CgppZiAoIXJlcXVpcmUoInN0cmluZ3IiKSkgewogIGluc3RhbGwucGFja2FnZXMoInN0cmluZ3IiKQogIGxpYnJhcnkoc3RyaW5ncikKfQoKaWYgKCFyZXF1aXJlKCJnZ2JpcGxvdCIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiZ2diaXBsb3QiKQogIGxpYnJhcnkoZ2diaXBsb3QpCn0KCmlmICghcmVxdWlyZSgia25pdHIiKSkgewogIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikKICBsaWJyYXJ5KGtuaXRyKQp9CgppZiAoIXJlcXVpcmUoInJwYXJ0IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJycGFydCIpCiAgbGlicmFyeShycGFydCkKfQoKaWYgKCFyZXF1aXJlKCJycGFydC5wbG90IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJycGFydC5wbG90IikKICBsaWJyYXJ5KHJwYXJ0KQp9CgppZiAoIXJlcXVpcmUoImNhcmV0IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJjYXJldCIpCiAgbGlicmFyeShjYXJldCkKfQogIAppZiAoIXJlcXVpcmUoImdncmVwZWwiKSkgewogIGluc3RhbGwucGFja2FnZXMoImdncmVwZWwiKQogIGxpYnJhcnkoZ2dyZXBlbCkKfQoKaWYgKCFyZXF1aXJlKCJnZW9zcGhlcmUiKSkgewogIGluc3RhbGwucGFja2FnZXMoImdlb3NwaGVyZSIpCiAgbGlicmFyeShnZ3JlcGVsKQp9CgppZiAoIXJlcXVpcmUoImdndGVybiIpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcygiZ2d0ZXJuIikKICBsaWJyYXJ5KGdncmVwZWwpCn0KCmlmICghcmVxdWlyZSgiZ2Vvc3BoZXJlIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJnZW9zcGhlcmUiKQogIGxpYnJhcnkoZ2Vvc3BoZXJlKQp9CmBgYAoKIyAxLjAgUHJvamVjdCBJbnRyb2R1Y3Rpb24KClRoZSBNYXJzIFByb2plY3QgaXMgZm9jdXNlZCBvbiBkYXRhIGZyb20gdGhlIDIwMjAgTWFycyBQZXJzZXZlcmFuY2UgUm92ZXIuIFRoZSBnb2FsIG9mIHRoZSBtaXNzaW9uIGlzIHRvIGxvb2sgZm9yIG1pY3JvYmlhbCBhbmNpZW50IGxpZmUgb3IgZm9ybXMgb2Ygd2F0ZXIgb24gTWFycyAodGhpbmdzIHRoYXQgY291bGQgc3VnZ2VzdCBsaWZlKS4gUGVyc2V2ZXJhbmNlIHVzZXMgbXVsdGlwbGUgaW5zdHJ1bWVudHMsIGluY2x1ZGluZyBQSVhMIChQbGFuZXRhcnkgSW5zdHJ1bWVudCBmb3IgWC1SYXkgTGl0aG9jaGVtaXN0cnkpLCBTSEVSTE9DIChTY2FubmluZyBIYWJpdGFibGUgRW52aXJvbm1lbnRzIHdpdGggUmFtYW4gYW5kIEx1bWluZXNjZW5jZSBmb3IgT3JnYW5pY3MgYW5kIENoZW1pY2FscykgYW5kIFNVUEVSQ0FNLiBTVVBFUkNBTSBoYXMgbXVsdGlwbGUgaW5zdHJ1bWVudHMgdGhhdCBtZWFzdXJlIHNwZWN0cm9zY29weSB0byBtZWFzdXJlIHByb3BlcnRpZXMgb2YgbWF0ZXJpYWxzIG9uIE1hcnMsIGluY2x1ZGluZyBMSUJTIChMYXNlci1pbmR1Y2VkIGJyZWFrZG93biBzcGVjdHJvc2NvcHkpLiBUaGlzIG5vdGVib29rIHdpbGwgcHJpbWFyaWx5IGZvY3VzIG9uIHRoZSBkYXRhIHdlIGhhdmUgYmVlbiBnaXZlbiBvZiBQSVhMIGFuZCBMSUJTLiAgCgojIDIuMCBPcmdhbml6YXRpb24gb2YgUmVwb3J0CgpUaGlzIHJlcG9ydCBpcyBvcmdhbml6ZSBhcyBmb2xsb3dzOiAKCiogU2VjdGlvbiAzLjAuICBGaW5kaW5nIDE6IExJQlMgYW5kIFBJWEwgTWF0Y2hpbmcgLSBXZSB3ZXJlIGFibGUgdG8gY29tYmluZSB0aGUgTElCUyBhbmQgUElYTCBkYXRhIHNldHMgYnkgcGlja2luZyBhIG1heGltdW0gZGlzdGFuY2UgdmFyaWFibGUgZnJvbSBhIFBJWEwgYWJyYXNpb24gYW5kIG1hdGNoaW5nIExJQlMgc2FtcGxlcyB0aGF0IHdlcmUgd2l0aGluIHRoZSBzZXQgZGlzdGFuY2Ugb2YgYSBQSVhMIGFicmFzaW9uLiAgCgoqIFNlY3Rpb24gNC4wOiBGaW5kaW5nIDI6IFNvaWwgQ29tcG9zaXRpb24gQW5hbHlzaXMgLSBVc2luZyB0aGUgTElCUyBhbmQgUElYTCBjb21iaW5lZCBkYXRhIHNldCwgSSBjcmVhdGVkIGEgcGxvdCBvZiB0aGUgY29tcG9zaXRpb24gcGVyY2VudGFnZXMgb2YgY2hlbWljYWwgY29tcG91bmRzIHN1Y2ggYXMgU2kwMiwgSzIwLCBldGMuIHVzaW5nIGxvZyBzY2FsaW5nIHRvIGNvbXBhcmUgdGhlIGNvbXBvc2l0aW9ucyBvZiBhIFBJWEwgYWJyYXNpb24gYW5kIHRoZSBjb3JyZXNwb25kaW5nIExJQlMgc2FtcGxlIGNvbXBvc2l0aW9ucyAoYmFzZWQgb24gdGhlIExJQlMgc2FtcGxlcyBmb3IgeCBkaXN0YW5jZSBhd2F5IGZyb20gYSBQSVhMIGFicmFzaW9uKS4KCiogU2VjdGlvbiA1LjAgRmluZGluZyAzOiBBbmFseXppbmcgQ2F0aW9uIENvbWJpbmF0aW9ucyB1c2luZyBMSUJTIGFuZCBQSVhMIG1hdGNoZWQgZGF0YTogVXNpbmcgdGhlIExJQlMgYW5kIFBJWEwgY29tYmluZWQgZGF0YSBzZXQsIHdlIGNyZWF0ZWQgYSB0ZXJuYXJ5IHBsb3QgdG8gc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIExJQlMgc2FtcGxlcyBzb3J0ZWQgYnkgd2hhdCBQSVhMIGFicmFzaW9uIHRoZXkgYXJlIGNsb3Nlc3QgdG8gKGJhc2VkIG9uIGEgY2hvc2VuIGRpc3RhbmNlIHZhcmlhYmxlKS4KCiogU2VjdGlvbiA2LjAgT3ZlcmFsbCBjb25jbHVzaW9ucyBhbmQgc3VnZ2VzdGlvbnMgCgoqIFNlY3Rpb24gNy4wIEFwcGVuZGl4IFRoaXMgc2VjdGlvbiBkZXNjcmliZSB0aGUgZm9sbG93aW5nIGFkZGl0aW9uYWwgd29ya3MgdGhhdCBtYXkgYmUgaGVscGZ1bCBpbiB0aGUgZnV0dXJlIHdvcms6IEFkZGl0aW9uYWwgU29pbCBDb21wb3NpdGlvbiBQbG90cyBvZiBMSUJTIGFuZCBQSVhMCgoKIyAzLjAgRmluZGluZyAxOiBQSVhMIGFuZCBMSUJTIE1hdGNoaW5nCgpGaXJzdGx5LCB3ZSB3aWxsIGJlIHRha2luZyBhIGxvb2sgYXQgaG93IFBJWEwgYW5kIExJQlMgY29ycmVzcG9uZC4gT3VyIGdyb3VwIGZvdW5kIHZlcnkgZWFybHkgaW4gb3VyIHJlc2VhcmNoIHRoYXQgdGhlcmUgd2Fzbid0IGEgZmVhdHVyZSBhbW9uZyB0aGVtIHRoYXQgY2FuIGJlIHVzZWQgdG8gbWF0Y2ggdGhlIGRhdGEgc2V0cy4gRm9yIGV4YW1wbGUsIHRoZSBjb2x1bW5zIG9mIFBJWEwgYXJlIG9yZ2FuaXplZCBieSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGFzIHdlbGwgYXMgc2FtcGxlIG51bWJlciAoMS0xNiksIHNhbXBsZSBuYW1lLCBhbmQgYWJyYXNpb24gbmFtZS4gVW5mb3J0dW5hdGVseSwgTElCUyB3YXNuJ3Qgc29ydGVkIHRoZSBzYW1lIHdheS4gTElCUyB3YXMgb3JnYW5pemVkIGJ5IHRoZSBzb2wgdGhhdCB0aGUgc2FtcGxlIHdhcyB0YWtlbiBhdC4gTElCUyBpcyBicm9rZW4gdXAgaW50byBtYW55IGRpZmZlcmVudCB0eXBlcyBvZiBzYW1wbGVzIGFzIHdlbGwsIGluY2x1ZGluZyB0aGUgZmFjdCBpdCBjYXJyaWVzIGFyb3VuZCBlYXJ0aCByZWZlcmVuY2UgZGF0YSB0byBiZSB1c2VkIGluIGNvbXBhcmluZyB3aXRoIGRpZmZlcmVudCBzYW1wbGUgc2l0ZXMuIFRoYXQgYmVpbmcgc2FpZCwgaW4gb3JkZXIgdG8gbWF0Y2ggUElYTCB0YXJnZXRzIHRvIGNvcnJlc3BvbmRpbmcgTElCUyBzYW1wbGVzLCBNYXJnbyBhbmQgSSBjcmVhdGVkIGEgbmV3IGRhdGEgc2V0IHRoYXQgYWRkZWQgYW5vdGhlciBtZXRhZGF0YSBmZWF0dXJlIHRvIFBJWEwgKGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgY29vcmRpbmF0ZXMpIHdoaWNoIHdlIG9idGFpbmVkIGZyb20gdGhlIEFuYWx5c3QncyBOb3RlYm9vay4gT25jZSB0aGlzIHdhcyBhZGRlZCBpbiwgd2UgcmVhbGl6ZWQgdGhhdCB0aGUgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBkaWRuJ3QgcmVhbGx5IG1hdGNoLiBTbyBNYXJnbyBjcmVhdGVkIGEgZGlzdGFuY2UgZnVuY3Rpb24gdG8gbWF0Y2ggTElCUyBzYW1wbGVzIHRvIFBJWEwgdGFyZ2V0cyBiYXNlZCBvbiB3aGF0ZXZlciBkaXN0YW5jZSBhIHBlcnNvbiBzcGVjaWZpZXMuIE9yaWdpbmFsbHksIHdlIHNldCBpdCB0byBiZSByb3VuZGVkIHRvIHRocmVlIHRob3VzYW5kdGhzIGFuZCBtYXRjaCBiYXNlZCBvbiB0aGF0LgoKVGhpcyBoZWxwZWQgYW5zd2VyIHRoZSBxdWVzdGlvbiBvZiBob3cgY2FuIHdlIGNvcnJlbGF0ZSB0aGUgTElCUyBhbmQgUElYTCBkYXRhIHNldHMgdG8gYmUgYWJsZSB0byBwbG90IHRoZW0gb24gdGhlIHNhbWUgYXhpcyBvZiB3aGF0ZXZlciBwbG90IGlzIHRyeWluZyB0byBiZSBjcmVhdGVkLiBJIHdhcyBjdXJpb3VzIHRvIHNlZSBob3cgY2xvc2UgUElYTCB0YXJnZXRzIHdlcmUgdG8gTElCUyBzYW1wbGUgc2l0ZXMgYXMgd2VsbCBhcyBob3cgbWFueSBMSUJTIHNhbXBsZXMgd291bGQgYmUgYXNzb2NpYXRlZCB3aXRoIGEgUElYTCB0YXJnZXQgcGVyaGFwcyB3aXRoIGEgcmFkaXVzIG9mIDcgb3IgMTAgbWV0ZXJzLgoKIyMgMy4xIERhdGEsIENvZGUsIGFuZCBSZXNvdXJjZXMKCjEuIHBldGVyY19maW5hbFByb2plY3RGMjQuUm1kICh3aXRoIGtuaXQgcGRmIGFuZCBodG1sKSBpcyB0aGlzIG5vdGVib29rLgpbaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDhfRmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNC5SbWRdKGh0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnROb3RlYm9va3MvQXNzaWdubWVudDA3X0RyYWZ0RmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNF9yb3VnaGRyYWZ0LlJtZCkKCgoyLiB2MV9saWJzX3RvX3NhbXBsZS5SZHMgaXMgdGhlIGNvbWJpbmVkIGRhdGEgc2V0IG9mIFBJWEwgYW5kIExJQlMgdGhhdCBpbmNsdWRlcyB0aGUgZGlzdGFuY2UgZnJvbSBhIFBJWEwgYWJyYXNpb24gdG8gYSBMSUJTIHNhbXBsZS4gIApbaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudERhdGEvdjFfbGlic190b19zYW1wbGUuUmRzXShodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9TdHVkZW50RGF0YS92MV9saWJzX3RvX3NhbXBsZS5SZHMpLiAKCkZpcnN0bHksIHdlIHNldCB0aGUgbnVtYmVyIG9mIG1ldGVycyBkaXN0YW5jZSB0aHJlc2hvbGQgYmV0d2VlbiBhIFBJWEwgYWJyYXNpb24gYW5kIExJQlMgc2FtcGxlLiBXaXRoaW4gdGhlIHYxX2xpYnNfdG9fc2FtcGxlLlJkcywgd2hpY2ggTWFyZ28gYW5kIEkgY29sbGFib3JhdGVkIG9uIHRoZXJlIGlzIGEgZGlzdGFuY2UgdmFyaWFibGUgdGhhdCBpcyBzZXQgdmlhIGEgZnVuY3Rpb24gdGhhdCBNYXJnbyBjcmVhdGVkIHRvIG1lYXN1cmUgdGhlIGRpc3RhbmNlIGJldHdlZW4gYSBQSVhMIGFicmFzaW9uIGFuZCBMSUJTIHNhbXBsZSB1c2luZyB0aGVpciBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGNvb3JkaW5hdGVzLiA3IG1ldGVycyBpcyB0aGUgYmVzdCBtZXRyaWMgYmVjYXVzZSB0aGF0IGlzIHRoZSBtYXhpbXVtIGRpc3RhbmNlIHRoZSBMSUJTIGluc3RydW1lbnQgY2FuIGFjY3VyYXRlbHkgY29sbGVjdCBkYXRhIGZyb20uCmBgYHtyfQptZXRlcnMgPC0gNwpgYGAKClRvIHByZXBhcmUgdGhlIGRhdGEsIHdlIHdpbGwgbG9hZCBpbiB0aGUgdjFfbGlic190b19zYW1wbGUuUmRzLCBncm91cCBieSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIG9mIExJQlMsIGFuZCBmaWx0ZXIgb3V0IGV2ZXJ5IExJQlMgc2FtcGxlIHRoYXQgaGFzIGEgbGFyZ2VyIGRpc3RhbmNlIGZyb20gaXRzIGNvcnJlc3BvbmRpbmcgUElYTCBhYnJhc2lvbiB0aGFuIHNwZWNpZmllZCBpbiB0aGUgY2hvc2VuIGRpc3RhbmNlIChtZXRlcikgdmFsdWUuIEluIG9yZGVyIHRvIG1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgdGhlIExJQlMgYW5kIFBJWEwgcG9pbnRzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lIG9mIGVhY2ggdW5pcXVlIFBJWEwgYWJyYXNpb24gYW5kIGl0cyBjb29yZGluYXRlcy4gVGhhdCBpcyB0aGUgdW5pcXVlX3BpeGwgZGF0YSBmcmFtZSB3aGljaCB3aWxsIGJlIHVzZWQgdG8gcGxvdCB0aGUgUElYTCBhYnJhc2lvbiBjb29yZGluYXRlcy4KCmBgYHtyIH0KbGlic190b19zYW1wbGUgPC0gcmVhZFJEUygifi9EQVItTWFycy1GMjQvU3R1ZGVudERhdGEvdjFfbGlic190b19zYW1wbGUuUmRzIikKI21ha2UgYSBmaWx0ZXJlZCBkYXRhIGZyYW1lIHRoYXQgcGlja3MgdGhlIG1heCBwb2ludCBvdXQgb2YgYWxsIGxpYnMgc2FtcGxlcyBhdCBhIGNlcnRhaW4gdGFyZ2V0IAojIGZvciBzaW1wbGljaXR5CmRmX2ZpbHRlcmVkIDwtIGxpYnNfdG9fc2FtcGxlICU+JQogIGdyb3VwX2J5KExhdC5saWJzLCBMb24ubGlicykgJT4lCiAgZmlsdGVyKFBvaW50LmxpYnMgPT0gbWF4KFBvaW50LmxpYnMpKSAlPiUKICB1bmdyb3VwKCkKZGZfZGlzdGFuY2VfZmlsdGVyIDwtIGRmX2ZpbHRlcmVkW2RmX2ZpbHRlcmVkJERpc3RhbmNlIDw9IG1ldGVycyxdCgojbWFrZSBhIGRhdGEgZnJhbWUgd2l0aCB0aGUgdW5pcXVlIHBpeGwgY29vcmRpbmF0ZXMgc2luY2UgdGhleSBhcmUgaW4gcGFpcnMgb2YgaWRlbnRpY2FsIGxhdC9sb24KdW5pcXVlX3BpeGwgPC0gZGZfZmlsdGVyZWQgJT4lCiAgc2VsZWN0KExhdC5waXhsLCBMb24ucGl4bCwgQWJyYXNpb24ucGl4bCkgJT4lIGRpc3RpbmN0KCkKYGBgCgoKIyMgMy4yIENvbnRyaWJ1dGlvbgoKVGhlIGxvZ2lzdGljcyBvZiBmaWx0ZXJpbmcgdGhlIG9yaWdpbmFsIGRhdGEgc2V0IGlzIG15IHdvcmsuIFByZXZpb3VzbHksIEkgaGFkIHRvIGRvIGEgbG90IG1vcmUgZmlsdGVyaW5nIGluIG9yZGVyIHRvIGNob29zZSB0aGUgZGlzdGFuY2UgYW5kIGdldCB1bmlxdWUgTElCUyBwb2ludHMgaW4gb3JkZXIgdG8gbm90IHB1dCB0b28gbWFueSBwb2ludHMgb24gdGhlIHNjYXR0ZXJwbG90LiBNYXJnbyBhbmQgSSB3b3JrZWQgdG9nZXRoZXIgdG8gY3JlYXRlIHRoZSBkYXRhIHNldCB0aGF0IEkgdXNlIGluIHRoaXMgc2VjdGlvbiAodjFfbGlic190b19zYW1wbGUuUmRzKSBieSBkZWNpZGluZyBob3cgdG8gbWF0Y2ggdXAgTElCUyB0byBjZXJ0YWluIFBJWEwgYWJyYXNpb25zLiBNYXJnbyBjcmVhdGVkIHRoZSBkaXN0YW5jZSBmdW5jdGlvbiB0byBmaW5kIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIFBJWEwgYWJyYXNpb25zIGFuZCBMSUJTIHNhbXBsZXMgYW5kIGFkZGVkIHRoYXQgY29sdW1uIHRvIHRoZSBkYXRhIHNldC4gVGhlbiwgRG9uYSBmaXhlZCBhbGwgdGhlIG5hbWluZyBjb252ZW50aW9ucyBpbiB0aGUgZGF0YSBzZXQgaW4gb3JkZXIgdG8gaGF2ZSBjb25zaXN0ZW5jeSBhbmQgbWFrZSBpdCBlYXN5IHRvIHRlbGwgd2hpY2ggdmFyaWFibGUgd2FzIG9yaWdpbmFsbHkgZnJvbSBlYWNoIGRhdGEgc2V0IChleC4gTmFtZS5waXhsLCBUYXJnZXQubGlicykuIEkgdGhlbiB1c2VkIHRoZSBkYXRhIHRvIGNyZWF0ZSBwbG90cyBhbmQgYW5hbHl6ZS4gQmVsb3cgaXMgYSBzY2F0dGVycGxvdCBzaG93Y2FzaW5nIHRoZSBkaXN0cmlidXRpb24gb2YgUElYTCBhYnJhc2lvbnMgYW5kIGNvcnJlc3BvbmRpbmcgTElCUyBzYW1wbGVzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgbWF4IGRpc3RhbmNlIGJldHdlZW4gdGhlbS4gCgoKIyMgMy4zIE1ldGhvZHMgRGVzY3JpcHRpb24gCgpJIGNob3NlIHRvIHVzZSBnZ3Bsb3QgdG8gZGlzcGxheSB0aGUgTElCUyBhbmQgUElYTCBkYXRhIGZvciBlYXNpZXIgYW5hbHlzaXMgb2Ygc2VlaW5nIGhvdyBtYW55IExJQlMgc2FtcGxlcyBhbGlnbiB3aXRoIGRpZmZlcmVudCBQSVhMIGFicmFzaW9ucy4gSXQgd2FzIHZlcnkgaW50ZXJlc3RpbmcgdG8gY2hhbmdlIGFyb3VuZCB0aGUgbWF4IGRpc3RhbmNlIGFuZCBzZWUgd2hpY2ggYWxpZ25lZCB3aXRoIHdoaWNoIGFicmFzaW9uLiBJbiB0ZXJtcyBvZiBleGVjdXRpb24sIGl0IHRvb2sgbWUgYSBiaXQgb2YgdGltZSB0byBvcmdhbml6ZSBhbGwgb2YgdGhlIHRob3VnaHRzIE1hcmdvIGFuZCBJIGhhZCBvbiBob3cgdG8gY3JlYXRlIGFuZCBtYW5hZ2UgdGhpcyBkYXRhIHNldC4gT3JpZ2luYWxseSwgd2UgaGFkIHJvdW5kZWQgdGhlIGRpc3RhbmNlcyB0byB0aGUgbmVhcmVzdCB0aG91c2FuZHRoIHRvIG1hdGNoIHRoZW0sIGFuZCB0aGVuIHdlcmUgcGxvdHRpbmcgdGhhdCB3YXkuIEhvd2V2ZXIsIHRoYXQgbGVmdCBhIGxvdCBvZiByb29tIGZvciBlcnJvciBhbmQgd2Fzbid0IGFzIGFjY3VyYXRlLiBDcmVhdGluZyBhIGRpc3RhbmNlIGZ1bmN0aW9uIGFsbG93cyBmb3IgdGhlIHNjaWVudGlzdCBvciBwZXJzb24gdXNpbmcgdGhlIE1hcnMgTWlzc2lvbiBNaW5kZXIgQXBwIHRvIGNob29zZSB3aGF0ZXZlciBkaXN0YW5jZSB0aGV5IHdvdWxkIGxpa2UgYW5kIGFsbG93cyBmb3IgbXVjaCBtb3JlIGZ1bmN0aW9uYWxpdHkuIE1vZGlmeWluZyB0aGUgZGF0YSBzZXQgbW9yZSBlbmRlZCB1cCBiZWluZyBtb3JlIGVmZmljaWVudCB0aGFuIGFkZGluZyBzbWFsbCBlZGl0cyBhcyBJIHdhcyBtYWtpbmcgbXkgcGxvdHMgd2hpY2ggd2FzIG9yaWdpbmFsbHkgbWFraW5nIG1lIGNyYXp5IChhcyBpbiBjaGFuZ2luZyB2YXJpYWJsZSB0eXBlcyBpZiB0aGV5IHdlcmVuJ3Qgd2hhdCB0aGV5IHdlcmUgc3VwcG9zZWQgdG8gYmUpLiBJbiB0aGUgZW5kLCBJIGxlYXJuZWQgYSBsb3QgYWJvdXQgZGF0YSBvcmdhbml6YXRpb24gYW5kIHRoYXQgY29uc2lzdGVuY3kgYW5kIHN0YXlpbmcgb3JnYW5pemVkIGlzIGtleSBhbmQgc2F2ZXMgYSBsb3Qgb2YgdGltZSBsYXRlciBvbi4KCgojIyAzLjQgUmVzdWx0IGFuZCBEaXNjdXNzaW9uIAoKVG8gY3JlYXRlIGEgcGxvdCBvZiB0aGUgTElCUyBhbmQgUElYTCBkYXRhIG9yZ2FuaXplZCBieSB3aGF0IExJQlMgc2FtcGxlcyBhbGlnbiB3aXRoIHdoYXQgYWJyYXNpb25zLCBmaXJzdCBwbG90dGVkIHRoZSBMSUJTIHNhbXBsZXMgY29sb3JlZCBieSB3aGF0IFBJWEwgYWJyYXNpb24gdGhleSB3ZXJlIGNsb3Nlc3QgdG8sIGFuZCB0aGVuIHBsb3R0ZWQgdGggUElYTCBhYnJhc2lvbnMgYXMgcmVkIHN0YXJzIG9uIHRoZSBwbG90IHRvIHNob3cgd2hlcmUgdGhlIFBJWEwgYWJyYXNpb25zIHdlcmUgcmVsYXRpdmUgdG8gdGhlIExJQlMgc2FtcGxlcy4KCmBgYHtyIH0KI3Bsb3Qgb2YgbGlicyBhbmQgcGl4bCBkYXRhIGJ5IGxhdC9sb24KZ2dwbG90KGRhdGEgPSBkZl9kaXN0YW5jZV9maWx0ZXIpICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IExvbi5saWJzLCB5ID0gTGF0LmxpYnMsIGNvbG9yID0gQWJyYXNpb24ucGl4bCkpICsgICAgICAgICAgICAgICAgICMgQ29sb3IgYnkgYWJyYXNpb24KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IExvbi5waXhsLCB5ID0gTGF0LnBpeGwpLCBkYXRhID0gdW5pcXVlX3BpeGwsIGNvbG9yID0gInJlZCIsIHNoYXBlID0gMywgc2l6ZSA9IDMpICsgIyBGaXhlZCBjb2xvciBmb3IgdW5pcXVlX3BpeGwgcG9pbnRzCiAgZ2VvbV90ZXh0X3JlcGVsKG1hcHBpbmcgPSBhZXMoeCA9IExvbi5waXhsLCB5ID0gTGF0LnBpeGwsIGxhYmVsID0gQWJyYXNpb24ucGl4bCksIGRhdGEgPSB1bmlxdWVfcGl4bCwKICAgICAgICAgICAgICAgICAgdmp1c3QgPSAyLCBjb2xvciA9ICJyZWQiKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJMSUJTIFNhbXBsZXMgYW5kIFBJWEwgQWJyYXNpb25zIHdpdGhpbiIsIG1ldGVycywgIm1ldGVycyIpLAogICAgICAgeCA9ICJMb25naXR1ZGUiLAogICAgICAgeSA9ICJMYXRpdHVkZSIsCiAgICAgICBjb2xvciA9ICJQSVhMIEFicmFzaW9uIiwKICAgICAgIGNhcHRpb24gPSAiRGF0YSBjb2xsZWN0ZWQgdXNpbmcgTElCUyBhbmQgUElYTCBpbnN0cnVtZW50cyBvbiBQZXJzZXJ2ZXJhbmNlIHJvdmVyLlxuIFNob3dzIFBJWEwgYWJyYXNpb25zIHBsb3R0ZWQgYXMgcmVkIHN0YXJzLFxuIGFuZCB0aGUgY29ycmVzcG9uZGluZyBMSUJTIHNhbXBsZXMgY29sb3JlZCBieSB0aGVpciBjbG9zZXN0IFBJWEwgYWJyYXNpb24uIikrICAgICAgICAgICMgTGFiZWwgZm9yIHRoZSBjb2xvciBsZWdlbmQgCiAjIENlbnRlciB0aGUgY2FwdGlvbiBvbiB0aGUgbGVmdCBzaWRlCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSAgIyBBbGlnbnMgY2FwdGlvbiB0byB0aGUgbGVmdAogICkKYGBgCldoZW4gbG9va2luZyBhdCB0aGlzIHBsb3QsIHRoZSBkYXRhIGZyYW1lIG9mIHRoZSBmaWx0ZXJlZCBMSUJTIGRhdGEgKGRmX2Rpc3RhbmNlX2ZpbHRlcikgYmFzZWQgb24gZGlzdGFuY2VzIHRvIGEgUElYTCBhYnJhc2lvbiBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gNyBtZXRlcnMgZmluZHMgMyBMSUJTIHNhbXBsZXMgY29ycmVzcG9uZGluZyB0byBBbGZhbGZhLCAyIGNvcnJlc3BvbmRpbmcgdG8gQmVsbGVncmFkZSwgMyBjb3JyZXNwb25kaW5nIHRvIERvdXJiZXMsIDcgY29ycmVzcG9uZGluZyB0byBOb3ZhcnVwdGEsIDQgY29ycmVzcG9uZGluZyB0byBRdWFydGllciwgYW5kIDkgY29ycmVzcG9uZGluZyB0byBUaG9ybnRvbiBHYXAuIAoKIyMgMy41IENvbmNsdXNpb25zLCBMaW1pdGF0aW9ucywgYW5kIEZ1dHVyZSBXb3JrLgoKSSBiZWxpZXZlIG15IGZpbmRpbmdzIG1ha2UgaXQgdmVyeSBlYXN5IGZvciByZXNlYXJjaGVycyBhbmQgc2NpZW50aXN0cyB0byBoYXZlIGEgdmlzdWFsaXphdGlvbiBvZiBQSVhMIGFuZCBMSUJTIHNhbXBsZXMgdGhhdCB0aGV5IHdhbnQgdG8gc2VlIGJhc2VkIG9uIHdoYXQgbWF4IGRpc3RhbmNlIHRoZXkgYXJlIGZvY3VzaW5nIG9uIHdoZW4gZXhhbWluaW5nIFBJWEwgYW5kIExJQlMgdG9nZXRoZXIuIEZvciBmdXR1cmUgd29yaywgSSB0aGluayBhcyBtb3JlIGNvb3JkaW5hdGVzIGFuZCBkYXRhIGlzIGFkZGVkIHRvIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cyBhcyB0aGV5IGJlY29tZSBhdmFpbGFibGUgZnJvbSBOQVNBIHRoaXMgd2lsbCBjb250aW51ZSB0byBiZSBidWlsdCB1cG9uIGFuZCBhbHRob3VnaCBpdCBpc24ndCBzdXBlciBjb21wbGljYXRlZCBvZiBhIHBsb3QsIGl0IHByb3ZpZGVzIGEgdmVyeSBuZWNlc3NhcnkgY29udGV4dCB0byB2aXN1YWxpemUgUElYTCBhbmQgTElCUy4gSSBkaWRuJ3QgZmluZCBtYW55IGxpbWl0YXRpb25zIGluIHRoaXMgcGxvdCBhcyBpdCBiYXNpY2FsbHkgaXMgb25seSBwcm92aWRpbmcgYW4gZWFzeSB2aXN1YWwgb2YgdGhlIFBJWEwgYW5kIExJQlMgZGF0YSB0b2dldGhlci4KCiMgNC4wIEZpbmRpbmcgMjogU29pbCBDb21wb3NpdGlvbiBBbmFseXNpcwoKVXNpbmcgdGhlIExJQlMgYW5kIFBJWEwgY29tYmluZWQgZGF0YSBzZXQsIEkgY3JlYXRlZCBhIHBsb3Qgb2YgdGhlIGNvbXBvc2l0aW9uIHBlcmNlbnRhZ2VzIG9mIGNoZW1pY2FsIGNvbXBvdW5kcyBzdWNoIGFzIFNpMDIsIEsyMCwgZXRjLiB1c2luZyBsb2cgc2NhbGluZyB0byBjb21wYXJlIHRoZSBjb21wb3NpdGlvbnMgb2YgYSBQSVhMIGFicmFzaW9uIGFuZCB0aGUgY29ycmVzcG9uZGluZyBMSUJTIHNhbXBsZSBjb21wb3NpdGlvbnMgKGJhc2VkIG9uIHRoZSBMSUJTIHNhbXBsZXMgZm9yIHggZGlzdGFuY2UgYXdheSBmcm9tIGEgUElYTCBhYnJhc2lvbikuIFRoZSBxdWVzdGlvbiBJIHdhcyB0cnlpbmcgdG8gYW5zd2VyIHdhcyBob3cgZG9lcyB0aGUgTElCUyBkYXRhIG9mIGEgY2VydGFpbiBhcmVhIGNvbXBhcmUgdG8gdGhlIFBJWEwgZGF0YSBvZiB0aGF0IGFyZWE/IEFyZSB0aGVyZSBtYW55IGRpZmZlcmVuY2VzIGJldHdlZW4gbG9jYXRpb25zIChtZWFuaW5nIHdoaWNoIGFicmFzaW9ucyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBMSUJTIHRhcmdldHMgYXJlIGRpZmZlcmVudCBhbmQgaW4gd2hhdCB3YXlzLCBkbyBpZ25lb3VzIHZzLiBzZWRpbWVudGFyeSBzaG93IGEgcGF0dGVybj8pLiBJbiBvcmRlciB0byBhY2NvbXBsaXNoIHRoaXMsIHdlIHdpbGwgdXNlIGEgZGlzdGFuY2UgZnVuY3Rpb24gdG8gZmlsdGVyIHdpdGhpbiA3IG1ldGVycyBvZiBkaXN0YW5jZSBiZXR3ZWVuIGEgUElYTCBzYW1wbGUgYW5kIExJQlMgdGFyZ2V0ICh0aGlzIGlzIHRoZSBtYXhpbXVtIGRpc3RhbmNlIG9mIGFjY3VyYWN5IGJhc2VkIG9uIE5BU0EncyBpbmZvcm1hdGlvbiBvbiBMSUJTIHNwZWN0cm9zY29weSBtYWNoaW5lcnkpLiBUaGVuLCB0aGUgZGF0YSBmb3IgZWFydGggcXVhcnRpbGUgcmVmZXJlbmNlcyAoZmlyc3QgYW5kIHRoaXJkIHF1YXJ0aWxlcyBhbmQgbWVkaWFuKSwgUElYTCBhYnJhc2lvbiBjaGVtaWNhbCBjb21wb3NpdGlvbiwgYW5kIGNvcnJlc3BvbmRpbmcgTElCUyB0YXJnZXQgY2hlbWljYWwgY29tcG9zaXRpb25zIHdpbGwgYmUgcGxvdHRlZCBiYXNlZCBvbiB0aGUgY2hvc2VuIFBJWEwgYWJyYXNpb24gKG9ubHkgb25lIGFicmFzaW9uIGlzIHBsb3R0ZWQgYXQgYSB0aW1lKS4gCgojIyA0LjEgRGF0YSwgQ29kZSwgYW5kIFJlc291cmNlcwoKMS4gcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNC5SbWQgKHdpdGgga25pdCBwZGYgYW5kIGh0bWwpIGlzIHRoaXMgbm90ZWJvb2suCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9TdHVkZW50Tm90ZWJvb2tzL0Fzc2lnbm1lbnQwOF9GaW5hbFByb2plY3ROb3RlYm9vay9wZXRlcmNfZmluYWxQcm9qZWN0RjI0LlJtZF0oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDdfRHJhZnRGaW5hbFByb2plY3ROb3RlYm9vay9wZXRlcmNfZmluYWxQcm9qZWN0RjI0X3JvdWdoZHJhZnQuUm1kKQoKMi4gcGV0ZXJjX2Fzc2lnbm1lbnQ1LlJtZCAod2l0aCBrbml0IHBkZiBhbmQgaHRtbCkgd2hpY2ggaXMgbXkgcHJldmlvdXMgbm90ZWJvb2suCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L3RyZWUvbWFpbi9TdHVkZW50Tm90ZWJvb2tzL0Fzc2lnbm1lbnQwNS9wZXRlcmNfYXNzaWdubWVudDA1LlJtZF0oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC90cmVlL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDUvcGV0ZXJjX2Fzc2lnbm1lbnQwNS5SbWRdKQoKMy4gc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcyB3aGljaCBpcyB0aGUgb3JpZ2luYWwgTElCUyBkYXRhIGdpdmVuIHRvIG91ciByZXNlYXJjaCBncm91cC4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkc10oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vRGF0YS9zdXBlcmNhbV9saWJzX21vY19sb2MuUmRzKQoKNC4gcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzLCB3aGljaCBpcyB0aGUgZGF0YSBzZXQgY29udGFpbmluZyB0aGUgUElYTCBkYXRhLCBzb2wsIGFuZCBjb29yZGluYXRlcy4KW2h0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnREYXRhL3BpeGxfc29sX2Nvb3JkaW5hdGVzLlJkc10oaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudERhdGEvcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzKQoKNC4gTElCU190cmFpbmluZ19zZXRfcXVhcnRpbGVzLlJkcyBpcyB0aGUgZGF0YSB3aXRoIGVhcnRoIHF1YXJ0aWxlIHJlZmVyZW5jZSBkYXRhLgpbaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vRGF0YS9MSUJTX3RyYWluaW5nX3NldF9xdWFydGlsZXMuUmRzXShodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9EYXRhL0xJQlNfdHJhaW5pbmdfc2V0X3F1YXJ0aWxlcy5SZHMpLiAKClRvIHByZXBhcmUgdGhlIGRhdGEsIEkgc3RhcnQgYnkgbG9hZGluZyBpbiB0aGUgTElCUyBkYXRhLiBUaGVuLCB3ZSBkcm9wIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gY29sdW1ucyBhbmQgc3VtIG9mIHBlcmNlbnRhZ2UgY29sdW1ucyBsZWF2aW5nIHVzIHdpdGgganVzdCB0aGUgd2VpZ2h0ZWQgY29tcG9zaXRpb24gaW4gdGVybXMgb2YgbnVtZXJpY2FsIGRhdGEuIFdlIGFsc28gcmVtb3ZlIHRoZSBzY2N0IHZhbHVlcywgYXMgdGhvc2UgdmFsdWVzIGFyZSB0aGUgb25lcyB0aGF0IGFyZSBlYXJ0aCByZWZlcmVuY2Ugc2FtcGxlcyB0aGF0IFBlcnNldmVyYW5jZSBjYXJyaWVzIHdpdGggaXQuIFRoZXJlZm9yZSwgdGhleSB3aWxsIG5vdCBiZSB2ZXJ5IHJlbGV2YW50IHdoZW4gcGxvdHRpbmcgdGhlIExJQlMgZGF0YSBhcyB3ZSBhcmUgZm9jdXNlZCBvbiB0aGUgTWFycyBzb2lsIGNvbXBvc2l0aW9ucy4KCmBgYHtyfQojRWFydGggcXVhcnRpbGVzCmVhcnRocXVhcnRpbGVzLmRmPC1yZWFkUkRTKCIvYWNhZGVtaWNzL01BVFAtNDkxMC1GMjQvREFSLU1hcnMtRjI0L0RhdGEvTElCU190cmFpbmluZ19zZXRfcXVhcnRpbGVzLlJkcyIpCiNMb2FkIGluIExJQlMgZGF0YQpsaWJzLmRmIDwtIHJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvRGF0YS9zdXBlcmNhbV9saWJzX21vY19sb2MuUmRzIikKI0Ryb3AgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBmZWF0dXJlcywgdGhlIHN1bSBvZiB0aGUgcGVyY2VudGFnZXMsIAojdGhlIGRpc3RhbmNlLCBhbmQgdGhlIHRvdGFsIGZyZXF1ZW5jaWVzCmxpYnMuZGYgPC0gbGlicy5kZiAlPiUgCiAgc2VsZWN0KCEoYyhkaXN0YW5jZV9tbSxUb3QuRW0uLFNpTzJfc3RkZXYsVGlPMl9zdGRldixBbDJPM19zdGRldixGZU9UX3N0ZGV2LAogICAgICAgICAgICAgTWdPX3N0ZGV2LE5hMk9fc3RkZXYsQ2FPX3N0ZGV2LEsyT19zdGRldixUb3RhbCkpKQojIENvbnZlcnQgdGhlIHBvaW50cyB0byBudW1lcmljCmxpYnMuZGYkcG9pbnQgPC0gYXMubnVtZXJpYyhsaWJzLmRmJHBvaW50KQpsaWJzLmRmWyw2OjEzXSA8LSBzYXBwbHkobGlicy5kZlssNjoxM10sYXMubnVtZXJpYykKI3JlbW92ZSB0aGUgc2NjdC9yZWZlcmVuY2Ugc2FtcGxlcwpsaWJzLmRmPC1saWJzLmRmJT4lCiAgZmlsdGVyKCEoZ3JlcGwoInNjY3QiLCB0YXJnZXQpKSkKI2FkZCBhIGNvbHVtbiB0byBpbmRpY2F0ZSB0aGUgbmVhcmVzdCBwaXhsCmxpYnMuZGY8LWNiaW5kKG5lYXJlc3RwaXhsPTAsbGlicy5kZikKI21ha2UgYSBkYXRhZnJhbWUgb2YganVzdCB0aGUgTElCUyBMYXQvTG9uZyBhbmQgdGFyZ2V0IG5hbWUgYW5kIHJlbW92ZSBkdXBsaWNhdGVzCmxpYnN0YXJnZXRzLmRmPC1saWJzLmRmWyxjKDEsMyw0LDUpXQpsaWJzdGFyZ2V0cy5kZjwtZGlzdGluY3QobGlic3RhcmdldHMuZGYpCmBgYAoKU2V0IG1ldGVycyBhbmQgY2hvc2VuIGFicmFzaW9uIHRvIGFjdCBhcyBhIHNsaWRlciBpbiB0aGUgMmQgYXBwLgpgYGB7cn0KI0Nob29zZSBtYXggZGlzdGFuY2UgdmFyaWFibGUgYmV0d2VlbiBQSVhMIGFuZCBMSUJTIGRhdGEKbWV0ZXJzID0gNwojQ2hvb3NlIFBJWEwgYWJyYXNpb24geW91IHdhbnQgdG8gbG9vayBhdAphYnJhc2lvbl9uYW1lID0gIlRob3JudG9uR2FwIgpgYGAKCk5leHQsIHdlIGxvYWQgaW4gdGhlIFBJWEwgZGF0YS4gV2UgcmVtb3ZlIHRoZSBhdG1vc3BoZXJpYyBzYW1wbGUgYW5kIG9ubHkgc2VsZWN0IG9uZSBQSVhMIHNhbXBsZSBvZiBlYWNoIGFicmFzaW9uLgpgYGB7ciwgZGF0YTAyfQojcmVhZCBpbiBwaXhsIGRhdGEgd2l0aCBsYXQvbG9uZwpwaXhsLmRmPC1yZWFkUkRTKCIvYWNhZGVtaWNzL01BVFAtNDkxMC1GMjQvREFSLU1hcnMtRjI0L1N0dWRlbnREYXRhL3BpeGxfc29sX2Nvb3JkaW5hdGVzLlJkcyIpCiNpbmNsdWRlIG9ubHkgcGl4bCBtZXRhZGF0YQpwaXhsLmRmPC1waXhsLmRmICU+JQogIHNlbGVjdChjKDEsMiwxOSwyMCwyMikpCiNjb252ZXJ0IExhdC9Mb25nIHRvIG51bWVyaWMKcGl4bC5kZiRMYXQgPC0gYXMubnVtZXJpYyhwaXhsLmRmJExhdCkKcGl4bC5kZiRMb25nIDwtIGFzLm51bWVyaWMocGl4bC5kZiRMb25nKQojcmVtb3ZlIHJvd3Mgc28gd2Ugb25seSBoYXZlIG9uZSBzYW1wbGUgcGVyIGFicmFzaW9uIGFuZCByZW1vdmUgYXRtb3NwaGVyaWMgc2FtcGxlCnBpeGwuZGY8LXBpeGwuZGZbYygyLDQsNiw4LDEwLDEyLDE0LDE2KSxdCmBgYAoKTmV4dCwgd2Ugd2lsbCBpbml0aWFsaXplIGEgZGlzdGFuY2UgdmFyaWFibGUgKHRvIGluZGljYXRlIGRpc3RhbmNlIGJldHdlZW4gUElYTCBhYnJhc2lvbiBhbmQgTElCUyB0YXJnZXQpIGFuZCBhbHNvIGluaXRpYWxpemUgZWFjaCBQSVhMIGFicmFzaW9uLCB3aGljaCB3aWxsIGJlIHVzZWQgdG8gbWFyayB3aGljaCBQSVhMIGFicmFzaW9uIHRoZSBMSUJTIHNhbXBsZSBpcyBjbG9zZXN0IHRvIGJ5IHVzaW5nIGEgZmFjdG9yIG9mIDAgb3IgMS4gCmBgYHtyfQpsaWJzdGFyZ2V0cy5kZjwtY2JpbmQobGlic3RhcmdldHMuZGYsIkRpc3RhbmNlIj0wLCJCZWxsZWdyYWRlIj0wLCJEb3VyYmVzIj0wLCJRdWFydGllciI9MCwiQWxmYWxmYSI9MCwiVGhvcm50b25HYXAiPTAsIkJlcnJ5IEhvbGxvdyI9MCwiTm92YXJ1cHRhIj0wLCJVZ2FuaWsgSXNsYW5kIj0wKQpgYGAKClRoZSBkaXN0YW5jZSBmdW5jdGlvbiBiZWxvdyB3aWxsIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIExJQlMgdGFyZ2V0IGFuZCBhbGwgdGhlIFBJWEwgYWJyYXNpb25zLCBhbmQgcGljayB0aGUgc21hbGxlc3QgZGlzdGFuY2UgdG8gcGljayB0aGUgY2xvc2VzdCBQSVhMIGFicmFzaW9uIHRvIHRoYXQgTElCUyB0YXJnZXQuCmBgYHtyfQpmb3IoaSBpbiAxOm5yb3cobGlic3RhcmdldHMuZGYpKSB7CiAgICBsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldPC1jKGRpc3RIYXZlcnNpbmUocGl4bC5kZlsxLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZlsyLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZlszLGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls0LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls1LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls2LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls3LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUocGl4bC5kZls4LGMoMSwyKV0sbGlic3RhcmdldHMuZGZbaSxjKDIsMyldLHI9MzM5MzE2OSkpCiAgICAKICAgIGxpYnN0YXJnZXRzLmRmW2ksMV08LXdoaWNoLm1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQogICAgbGlic3RhcmdldHMuZGZbaSw1XTwtbWluKGxpYnN0YXJnZXRzLmRmW2ksYyg2OjEzKV0pCn0KbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw8LWFzLmZhY3RvcihsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCkKbGV2ZWxzKGxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsKTwtKGMoIkJlbGxlZ3JhZGUiLCJEb3VyYmVzIiwiUXVhcnRpZXIiLCJBbGZhbGZhIiwiVGhvcm50b25HYXAiLCJCZXJyeSBIb2xsb3ciLCJOb3ZhcnVwdGEiLCJVZ2FuaWsgSXNsYW5kIikpCmBgYAoKQmVsb3cgaXMgYW5vdGhlciBpbml0aWFsaXplciBmb3IgdGhlIFBJWEwgYWJyYXNpb24gZGF0YS4gVGhpcyBzZXRzIHRoZSB2YXJpYWJsZXMgZm9yIGVhY2ggUElYTCBhYnJhc2lvbi4KYGBge3J9CkJlbGxlZ3JhZGU8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVsbGVncmFkZSIsXSR0YXJnZXQKRG91cmJlczwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJEb3VyYmVzIixdJHRhcmdldApRdWFydGllcjwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJRdWFydGllciIsXSR0YXJnZXQKQWxmYWxmYTwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJBbGZhbGZhIixdJHRhcmdldApUaG9ybnRvbkdhcDwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJUaG9ybnRvbkdhcCIsXSR0YXJnZXQKQmVycnlIb2xsb3c8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVycnkgSG9sbG93IixdJHRhcmdldApOb3ZhcnVwdGE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iTm92YXJ1cHRhIixdJHRhcmdldApVZ2FuaWtJc2xhbmQ8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVWdhbmlrIElzbGFuZCIsXSR0YXJnZXQKYGBgCgpOZXh0LCB3ZSBmaWx0ZXIgb3V0IHRoZSBMSUJTIHRhcmdldHMgdGhhdCBhcmUgbm90IHdpdGhpbiB0aGUgc3BlY2lmaWVkIGRpc3RhbmNlIHZhcmlhYmxlLiBUaGVuLCB3ZSBtZXJnZSB0aGUgTElCUyBkYXRhIHdpdGggdGhlIHJlc3BlY3RpdmUgUElYTCBhYnJhc2lvbiBieSBtdXRhdGluZyBhbmQgYWRkaW5nIGFuIGFicmFzaW9uIGNvbHVtbiB0aGF0IGhhcyB0aGUgYWJyYXNpb24gbmFtZSBjbG9zZXN0IHRvIGVhY2ggTElCUyB0YXJnZXQuIFdlIGFsc28gYWRkIGEgY29sdW1uLCBMSUJTIG9yIFBJWEwsIHdoaWNoIGRlbm90ZXMgaWYgdGhlIHJvdyBvZiBkYXRhIGlzIGZyb20gdGhlIFBJWEwgYW5kIExJQlMgZGF0YSBzZXRzLgpgYGB7cn0KaW5jbHVkZWQubGliczwtKGxpYnN0YXJnZXRzLmRmJT4lCiAgZmlsdGVyKERpc3RhbmNlPG1ldGVycykpJHRhcmdldApsaWJzLm1hdHJpeCA8LWxpYnMuZGYgJT4lCiAgZmlsdGVyKHRhcmdldCAlaW4lIGluY2x1ZGVkLmxpYnMpCmxpYnMubWF0cml4IDwtIGxpYnMubWF0cml4WyxjKDUsNzoxNCldCmxpYnMubWF0cml4PC1saWJzLm1hdHJpeFssYygxOjIsNDo5LDMpXQpsaWJzLm1hdHJpeDwtY2JpbmQoIkFicmFzaW9uIj0wLGxpYnMubWF0cml4KQpsaWJzLm1hdHJpeDwtbGlicy5tYXRyaXglPiUKICBtdXRhdGUoQWJyYXNpb24gPSBpZmVsc2UodGFyZ2V0JWluJUFsZmFsZmEsIkFsZmFsZmEiLCAKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgQmVsbGVncmFkZSwgIkJlbGxlZ3JhZGUiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBCZXJyeUhvbGxvdywgIkJlcnJ5IEhvbGxvdyIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIERvdXJiZXMsICJEb3VyYmVzIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgTm92YXJ1cHRhLCAiTm92YXJ1cHRhIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgUXVhcnRpZXIsICJRdWFydGllciIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFRob3JudG9uR2FwLCAiVGhvcm50b25HYXAiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBVZ2FuaWtJc2xhbmQsICJVZ2FuaWsgSXNsYW5kIixBYnJhc2lvbikpKSkpKSkpKQpsaWJzLm1hdHJpeDwtY2JpbmQobGlic29ycGl4bD0xLGxpYnMubWF0cml4KQpgYGAKCk5leHQsIHdlIHdpbGwgcmVhZCBpbiB0aGUgUElYTCBkYXRhLiBXZSB3aWxsIHJlbW92ZSB0aGUgYXRtb3NwaGVyaWMgc2FtcGxlIChmaXJzdCBzYW1wbGUpIGFuZCBvbmx5IGNob29zZSBvbmUgb2YgZWFjaCBQSVhMIHNhbXBsZSBpbiBhcyBlYWNoIGFicmFzaW9uIGhhcyB0d28gc2FtcGxlcyAob25seSBvbmUgd2lsbCBiZSBuZWNlc3NhcnkgZm9yIHRoZSBwbG90KS4KCmBgYHtyLCBkYXRhMDN9CiNyZWFkIGluIHBpeGwgZGF0YSB3aXRoIGxhdC9sb25nCnBpeGwuZGY8LXJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvU3R1ZGVudERhdGEvcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzIikKcGl4bC5kZjwtcGl4bC5kZiAlPiUKICBzZWxlY3QoYyg1OjgsMTI6MTQsMTcsMTksMTgsMjIpKQojcmVvcmRlciBwaXhsIGNvbHVtbnMgc28gdGhhdCBpdCBtYXRjaGVzIGxpYnMgZGF0YSBvcmdhbml6YXRpb24KcGl4bC5kZjwtcGl4bC5kZlssYygxMSwxMCw0LDMsOCwyLDYsMSw1LDcpXQojcmVtb3ZlIGF0bW9zcGhlcmljIHNhbXBsZQpwaXhsLmRmPC1waXhsLmRmWzI6MTYsXQpwaXhsLmRmPC1jYmluZChsaWJzb3JwaXhsPTAscGl4bC5kZikKYGBgCgpGaW5hbGx5LCB3ZSBtZXJnZSB0aGUgTElCUyBhbmQgUElYTCBkYXRhIHNldHMgd2UgaGF2ZSBtb2RpZmllZCB0aHVzIGZhciBmb3IgYSBjb21iaW5lZCBMSUJTIGFuZCBQSVhMIGRhdGEgZnJhbWUgc3VpdGFibGUgZm9yIGEgc29pbCBjb21wb3NpdGlvbiBsaW5lIHBsb3QuCmBgYHtyfQpjb2xuYW1lcyhwaXhsLmRmKTwtY29sbmFtZXMobGlicy5tYXRyaXgpCnBpeGxsaWJzLmRmPC1yYmluZChwaXhsLmRmLGxpYnMubWF0cml4KQpgYGAKCiMjIDQuMiBDb250cmlidXRpb24KClNvbWUgb2YgdGhlIGRhdGEgbWFuaXB1bGF0aW5nIHdvcmsgd2FzIE1hcmdvJ3MsIHN1Y2ggYXMgdGhlIGRpc3RhbmNlIGZ1bmN0aW9uLiBJbiB0ZXJtcyBvZiBwaXZvdGluZyB0aGUgZGF0YSBmcmFtZSBhbmQgdGhlIG90aGVyIHN0ZXBzIG9mIHRoZSBwcmVwcm9jZXNzaW5nIGlzIG15IG93biB3b3JrLiBUaGUgbWFuaXB1bGF0aW5nIGFuZCBzZXR1cCBvZiBkYXRhIGJlbG93IHRvIHBsb3QgdGhlIGxpbmUgc29pbCBjb21wb3NpdGlvbiBwbG90cyBpcyBteSBvd24uIE1hcmdvIGFuZCBJIHdvcmtlZCB0b2dldGhlciB0byBjcmVhdGUgdGhlIGRhdGEgc2V0cyB1c2VkLiBJbiBvdXIgcHJlc2VudGF0aW9uLCBEYXZpZCB3YXMgYWJsZSB0byBjcmVhdGUgYSBmYWNpZCBncmlkIHRvIGNvbXBsaW1lbnQgbXkgc2luZ2xlIGFicmFzaW9uIGFuYWx5c2lzIHdoaWNoIHNob3dlZCB0aGUgYXZlcmFnZSBMSUJTIHRhcmdldCBjaGVtaWNhbCBjb21wb3NpdGlvbiBhbmQgY29ycmVzcG9uZGluZyBQSVhMIGFicmFzaW9uIGNvbXBvc2l0aW9uLiBUaGlzIHdhcyBkb25lIGluIFJTaGlueSBhbmQgaW1wbGVtZW50ZWQgaW4gdGhlIGFwcCwgc28gSSBmZWx0IHRoYXQgcmVkb2luZyB0aGUgc2FtZSBwbG90IHdvdWxkbid0IGJlIG5lY2Vzc2FyeS4gSSBmb2N1c2VkIG9uIHBsb3R0aW5nIG9uZSBzcGVjaWZpYyBhYnJhc2lvbiB0byBwcm92aWRlIG1vcmUgaW4gZGVwdGggYW5hbHlzaXMgb2Ygb25lIGFicmFzaW9uIGFuZCB0aGUgc3Vycm91bmRpbmcgYXJlYSBzaW5jZSBEYXZpZCB3YXMgYWJsZSB0byBwcm92aWRlIG1vcmUgY29udGV4dCBhbmQgcGxvdCB0aGUgUElYTCBhYnJhc2lvbnMgYWxsIGF0IG9uY2UuCgojIyA0LjMgTWV0aG9kcyBEZXNjcmlwdGlvbiAKCldoZW4gZGVjaWRpbmcgaG93IHRvIGFwcHJvYWNoIHRoZSBjb25jZXB0IG9mIGJ1aWxkaW5nIHNvaWwgY29tcG9zaXRpb24gcGxvdHMgb2YgZWFjaCBQSVhMIGFicmFzaW9uIGFuZCB0aGUgY29ycmVzcG9uZGluZyBMSUJTIHRhcmdldHMgd2l0aGluIGEgY2VydGFpbiBkaXN0YW5jZSBtYXhpbXVtLCBJIGRlY2lkZWQgdGhlIGJlc3Qgd2F5IHdhcyB0byBzdGFydCB3aXRoIHRoZSBvcmlnaW5hbCBkYXRhIHNldHMgYW5kIG1vZGlmeSB0aGVtIGFzIG5lZWRlZC4gRm9yIHRoZSBhY3R1YWwgcGxvdCwgdGhlIGJlc3Qgd2F5IHRvIGZvcm1hdCB0aGUgZGF0YSBjb3JyZWN0bHkgaXMgdG8gcGl2b3QgaXQsIGFzIEkgbmVlZCB0aGUgeCBheGlzIHRvIGJlIHRoZSBjb2x1bW4gbmFtZXMgaW4gdGhlIGN1cnJlbnQgZGF0YSBmcmFtZSB3ZSBoYXZlIChTaU8yIGFuZCBvdGhlciBjb21wb3NpdGlvbnMpIGFuZCB0aGUgeSBheGlzIHRvIGJlIHRoZSB3ZWlnaHRlZCBjb21wb3NpdGlvbiB2YWx1ZXMuIFdlIGFsc28gbmVlZCBhbiBpbmRpY2F0b3Igb2YgaWYgdGhlIGRhdGEgaXMgZnJvbSBQSVhMIG9yIExJQlMsIHdoaWNoIGFsc28gaXMgaGVscGZ1bCBmb3IgYnVpbGRpbmcgdGhlIGxpbmUgcGxvdHMuIAoKVXNlcnMgd2lsbCBoYXZlIHRvIHNldCB0aGUgZGlzdGFuY2UgdmFyaWFibGUgaW4gb3JkZXIgdG8gY2hvb3NlIHRoZSBtYXhpbXVtIGRpc3RhbmNlIGJldHdlZW4gUElYTCBhYnJhc2lvbnMgYW5kIExJQlMgdGFyZ2V0cy4gVGhpcyBjYW4gdmFzdGx5IGNoYW5nZSB0aGUgbnVtYmVyIG9mIGxpbmVzIG9uIHRoZSBwbG90cyB3aGljaCBjYW4gaGVscCBwcmV2ZW50IG92ZXJjcm93ZGVkIHBsb3RzLiBVc2VycyBhbHNvIGNhbiBzZXQgYSB2YXJpYWJsZSB0byBjaG9vc2UgYSBzcGVjaWZpYyBQSVhMIGFicmFzaW9uIGFuZCBjb3JyZXNwb25kaW5nIExJQlMgdGFyZ2V0cywgd2hpY2ggaXMgZWFzaWVyIHRvIGludGVycHJldCBhcyBwbG90dGluZyBhbGwgb2YgdGhlIExJQlMgYW5kIFBJWEwgY29tcG9zaXRpb24gaW5mb3JtYXRpb24gb24gbGluZSBwbG90cyBsZWFkcyB0byB2ZXJ5IGNvbmRlbnNlZCBncmFwaHMgdGhhdCBhcmUgaGFyZCB0byByZWFkLgoKIyMgNC40IFJlc3VsdCBhbmQgRGlzY3Vzc2lvbiAKCkZpcnN0LCB3ZSB3aWxsIHR1cm4gdGhlIGVhcnRoIHF1YXJ0aWxlIGluZm9ybWF0aW9uIGludG8gYSBsb25nIGRhdGEgZnJhbWUgKG1lYW5pbmcgcGl2b3RpbmcgdGhlIGNvbHVtbnMgaW50byB0aGUgdmFsdWVzKSBhbmQgb25seSBzZWxlY3QgdGhlIGZpcnN0IGFuZCB0aGlyZCBxdWFydGlsZSByb3dzLiAKYGBge3J9CiMgRWFydGggcXVhcnRpbGVzCmZpbHRlcmVkX3Jvd3MgPC0gZWFydGhxdWFydGlsZXMuZGYgJT4lCiAgZmlsdGVyKGBUcmFpbmluZyBzZXQgUXVhcnRpbGVzYCAlaW4lIGMoIjFzdCIsICIzcmQiLCAiTWVkIikpCmVhcnRocXVhcnRpbGVzX2xvbmcgPC0gZmlsdGVyZWRfcm93cyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJTaU8yIik6bGFzdF9jb2woKSwgbmFtZXNfdG8gPSAiQ29tcG91bmQiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSIpCgplYXJ0aHF1YXJ0aWxlc19sb25nIDwtIGVhcnRocXVhcnRpbGVzX2xvbmcgJT4lIHJlbmFtZShRdWFydGlsZXMgPSBgVHJhaW5pbmcgc2V0IFF1YXJ0aWxlc2ApCmBgYAoKVGhlbiwgdGhlIGRhdGEgd2lsbCBiZSBmaWx0ZXJlZCB0byBvbmx5IGluY2x1ZGUgdGhlIGRhdGEgZnJvbSBhIHNwZWNpZmljIFBJWEwgYWJyYXNpb24gY2hvc2VuIGJ5IHRoZSB1c2VyLiBUaGUgZGF0YSBpcyBwaXZvdGVkIGludG8gYSBsb25nIGZvcm1hdCwgYW5kIHRoZSBjb2x1bW5zIGFyZSByZW9yZGVyZWQgdG8gbWltaWMgc2ltaWxhciBwbG90cyBmcm9tIE5BU0EgcGFwZXJzLgpgYGB7cn0KIyBGaWx0ZXIgZm9yIHRoZSBzcGVjaWZpYyBhYnJhc2lvbiBzYW1wbGUsIGUuZy4sICJBbGZhbGZhIgpwaXhsbGlic19maWx0ZXJlZCA8LSBwaXhsbGlicy5kZiAlPiUKICBmaWx0ZXIoQWJyYXNpb24gPT0gYWJyYXNpb25fbmFtZSkKCiMgUGl2b3QgdGhlIGRhdGEgdG8gbG9uZ2VyIGZvcm1hdCBmb3IgZ2dwbG90CnBpeGxsaWJzX2xvbmcgPC0gcGl4bGxpYnNfZmlsdGVyZWQgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiU2lPMiIpOmxhc3RfY29sKCksIG5hbWVzX3RvID0gIkNvbXBvdW5kIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2UiKQoKZGVzaXJlZF9vcmRlciA8LSBjKCJTaU8yIiwgIkFsMk8zIiwgIkZlT1QiLCAiTWdPIiwgIkNhTyIsICJOYTJPIiwgIksyTyIsICJUaU8yIikgICMgU3BlY2lmeSB5b3VyIGN1c3RvbSBvcmRlciBoZXJlCnBpeGxsaWJzX2xvbmckQ29tcG91bmQgPC0gZmFjdG9yKHBpeGxsaWJzX2xvbmckQ29tcG91bmQsIGxldmVscyA9IGRlc2lyZWRfb3JkZXIpCmBgYAoKRm9yIHRoZSBwbG90LCB3ZSB1c2UgZ2dwbG90IHRvIHBsb3QgdGhlIHBpeGxsaWJzX2xvbmcgZGF0YSBmcmFtZSB3ZSBjcmVhdGVkLiBUaGUgcGxvdCBpcyBjb2xvcmVkIGJ5IGlmIHRoZSBsaW5lIGlzIGEgUElYTCBhYnJhc2lvbidzIGNvbXBvc2l0aW9uIG9yIGEgTElCUyB0YXJnZXQncyBjb21wb3NpdGlvbi4gV2UgYWxzbyBhZGQgYSBsYXllciB3aXRoIHRoZSBlYXJ0aCBxdWFydGlsZSBpbmZvcm1hdGlvbiwgd2hpY2ggaXMgdGhlIGRvdHRlZCBsaW5lcy4gVGhlIHdlaWdodCBwZXJjZW50YWdlcyBvbiB0aGUgeSBheGlzIGFyZSBsb2cgc2NhbGVkIGFzIGl0IG1ha2VzIHRoZSBwbG90IG1vcmUgcmVhZGFibGUsIGJ1dCB0aGlzIGNhbiBiZSBlZGl0ZWQgKHdpbGwgYmUgYWRkZWQgYXMgYSB0b2dnbGUgaW4gdGhlIGFwcCkuCmBgYHtyfQojIE1hcCB0aGUgUElYTC9MSUJTIGNvbHVtbiB0byBjb2xvciBhbmQgdXNlIHRhcmdldF9uYW1lIHRvIGRpZmZlcmVudGlhdGUgbGluZXMKc3VwcHJlc3NXYXJuaW5ncyhnZ3Bsb3QocGl4bGxpYnNfbG9uZywgYWVzKHggPSBDb21wb3VuZCwgeSA9IFBlcmNlbnRhZ2UsIGNvbG9yID0gYXMuZmFjdG9yKGxpYnNvcnBpeGwpLCBncm91cCA9IHRhcmdldCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogICMgQWRkIEVhcnRoIHF1YXJ0aWxlIGxpbmVzIHVzaW5nIGVhcnRocXVhcnRpbGVzX2xvbmcKICBnZW9tX2xpbmUoZGF0YSA9IGVhcnRocXVhcnRpbGVzX2xvbmcsIGFlcyh4ID0gQ29tcG91bmQsIHkgPSBQZXJjZW50YWdlLCBsaW5ldHlwZSA9IFF1YXJ0aWxlcywgZ3JvdXAgPSBRdWFydGlsZXMpLCAKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTb2lsIENvbXBvc2l0aW9uIGZvciBQSVhMIixhYnJhc2lvbl9uYW1lLCJhbmQgTElCUyB3aXRoaW4iLCBtZXRlcnMsICJtZXRlcnMiLCBzZXAgPSAiICIpLAogICAgICAgeCA9ICJDaGVtaWNhbCBDb21wb3VuZCIsCiAgICAgICB5ID0gIldlaWdodCBQZXJjZW50YWdlIiwKICAgICAgIGNvbG9yID0gIk1lYXN1cmVtZW50IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiUXVhcnRpbGVzIiwKICAgICAgIGNhcHRpb24gPSAiVGhlIGNoZW1pY2FsIGNvbXBvc2l0aW9uIG9mIGEgUElYTCBhYnJhc2lvbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyB0YXJnZXRzIFxuIHdpdGhpbiBzcGVjaWZpZWQgZGlzdGFuY2Ugb2YgcmVzcGVjdGl2ZSBhYnJhc2lvbi4iKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImJsdWUiLCAiMSIgPSAicmVkIiksIGxhYmVscyA9IGMoIlBJWEwiLCAiTElCUyIpKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNSwgeSA9IC41MCwgbGFiZWwgPSAiMXN0IFF1YXJ0aWxlIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMiwgbGFiZWwgPSAiTWVkaWFuIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMTAsIGxhYmVsID0gIjNyZCBRdWFydGlsZSIsIGNvbG9yID0gImJsYWNrIiwgaGp1c3QgPSAwKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgICAgIyBDZW50ZXIgdGhlIGNhcHRpb24gb24gdGhlIGxlZnQgc2lkZQogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkgICMgQWxpZ25zIGNhcHRpb24gdG8gdGhlIGxlZnQKICApKQoKYGBgClRvIHNhdmUgc3BhY2UgaW4gdGhpcyBub3RlYm9vaywgSSBkaWQgbm90IHBsb3QgZWFjaCBhYnJhc2lvbiAoYmFzZWQgb24gY2hvc2VuIGFicmFzaW9uIHZhcmlhYmxlIG5hbWUpLiBJbiBjb21wYXJpbmcgZWFjaCBQSVhMIGFicmFzaW9uIGFuZCB0aGUgY29ycmVzcG9uZGluZyBMSUJTIHRhcmdldHMsIEkgZm91bmQgdGhhdCB0aGUgUElYTCBhYnJhc2lvbnMgY29ycmVzcG9uZGluZyB0byBpZ25lb3VzIGhhZCB2ZXJ5IHNpbWlsYXIgcGxvdHMsIHdoaWxlIHRoZSBQSVhMIGFicmFzaW9ucyBjb3JyZXNwb25kaW5nIHRvIHNlZGltZW50YXJ5IGhhZCB2ZXJ5IHNpbWlsYXIgcGxvdHMuIFRoZSBpZ25lb3VzL3NlZGltZW50YXJ5IGluZGljYXRvciBpcyBzaG93biBpbiB0aGUgUElYTCBkYXRhLiBBbiBpbnRlcmVzdGluZyB0aGluZyB0byBub3RlIGlzIHRoYXQgZm9yIHNvbWUgYWJyYXNpb25zLCBsaWtlIEFsZmFsZmEgYW5kIFRob3JudG9uR2FwLCB0aGUgY2hlbWljYWwgY29tcG9zaXRpb25zIG9mIGJvdGggUElYTCBzYW1wbGVzIGluIHRoZSBhYnJhc2lvbiBhcmUgdGhlIHNhbWUuIEZvciBvdGhlciBhYnJhc2lvbnMsIGxpa2UgQmVsbGVncmFkZSwgdGhlIGNoZW1pY2FsIGNvbXBvc2l0aW9ucyBvZiB0aGUgUElYTCBzYW1wbGVzIGluIHRoZSBCZWxsZWdyYWRlIGFicmFzaW9uIGRpZmZlci4gQWxzbywgbWFueSBvZiB0aGUgcGxvdHMgaGFkIGEgZmV3IHBvaW50cyB3aXRoIHZlcnkgbG93IEsyTyB3aGljaCBzZWVtcyBsaWtlIGEgbWFqb3Igb3V0bGllci4KCiMjIDQuNSBDb25jbHVzaW9ucyBhbmQgRnV0dXJlIFdvcmsKVGhpcyBmaW5kaW5nIGNhbiBiZSB1c2VkIGJ5IGdlb2xvZ2lzdHMgdG8gYW5hbHl6ZSB3aGF0IGRpZmZlcmVudCBzb2lsIGNvbXBvc2l0aW9ucyBhcm91bmQgZGlmZmVyZW50IFBJWEwgYWJyYXNpb25zIGNhbiBtZWFuIGZvciBsaWZlIG9uIE1hcnMuIEZvciBleGFtcGxlLCBveGlkZSBwcmVzZW5jZSBkb2Vzbid0IG5lY2Vzc2FyaWx5IGluZGljYXRlIGxpZmUsIGJ1dCBpdCBjb3VsZCBpbmRpY2F0ZSBiaW9sb2dpY2FsIG9yIGNoZW1pY2FsIGxpZmUgcHJvY2Vzc2VzLiBGb3IgZXhhbXBsZSwgQ2FPIGNhbiBpbmRpY2F0ZSB0aGUgcHJlc2VuY2Ugb2Ygb2xkIGJpb2xvZ2ljYWwgbWF0ZXJpYWwgbGlrZSBzaGVsbHMgb3IgZm9zc2lscy4gRm9yIGZ1dHVyZSB3b3JrLCBJIHdvdWxkIGxpa2UgdG8gc2VlIHdoeSBjZXJ0YWluIGFicmFzaW9ucyBkaWZmZXIgaW4gdGhlaXIgUElYTCBjb3JlIHNhbXBsZSBjb21wb3NpdGlvbi4gSXMgdGhpcyBiYXNlZCBvbiB0aGUgcmVzZWFyY2ggZG9uZSBieSBzY2llbnRpc3RzIGluIHNlbGVjdGluZyBzcGVjaWZpYyBhYnJhc2lvbnMgYW5kIHRyeWluZyB0byBvYnRhaW4gZGlmZmVyaW5nIHNhbXBsZXMgZm9yIGFicmFzaW9ucyBpbiBjZXJ0YWluIGFyZWFzPyBPciBpcyB0aGlzIGJ5IGNoYW5jZT8gT3IgaXMgaXQgc2ltcGx5IHNob3dpbmcgbW9yZSByb2NrIHZhcmlldHkgb3Igd2VhdGhlcmluZyB0aGUgY2VydGFpbiBhYnJhc2lvbnM/CgojIDUuMCBGaW5kaW5nIDM6IEFuYWx5emluZyBDYXRpb24gQ29tYmluYXRpb25zIHVzaW5nIExJQlMgYW5kIFBJWEwgbWF0Y2hlZCBkYXRhClVzaW5nIHRoZSBMSUJTIGFuZCBQSVhMIGNvbWJpbmVkIGRhdGEgc2V0LCB3ZSBjcmVhdGVkIGEgdGVybmFyeSBwbG90IHRvIHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiBMSUJTIHNhbXBsZXMgc29ydGVkIGJ5IHdoYXQgUElYTCBhYnJhc2lvbiB0aGV5IGFyZSBjbG9zZXN0IHRvIChiYXNlZCBvbiBhIGNob3NlbiBkaXN0YW5jZSB2YXJpYWJsZSkuIE11Y2ggb2YgdGhlIGRhdGEgcHJlcHJvY2Vzc2luZyBpcyBzaW1pbGFyIHRvIEZpbmRpbmcgMSB3aGljaCB3ZSB3aWxsIHJlcGVhdCBoZXJlLiBJdCB3aWxsIGludm9sdmUgdXNpbmcgYSBkaXN0YW5jZSBmdW5jdGlvbiB0byBjb3JyZWxhdGUgTElCUyB0YXJnZXRzIHdpdGggUElYTCBzYW1wbGVzLCBtYXRjaGluZyB0aGUgZGF0YSBiYXNlZCBvbiB0aGUgY2xvc2VzdCBQSVhMIHNhbXBsZSwgYW5kIHBsb3R0aW5nIHRoZSBMSUJTIGRhdGEgKGNvbG9yZWQgYnkgY29ycmVzcG9uZGluZyBQSVhMIGFicmFzaW9uKSBhbmQgdGhlIFBJWEwgYWJyYXNpb25zIG9uIGEgdGVybmFyeSBwbG90LiBUaGUgZ29hbCBoZXJlIGlzIHRvIGFuYWx5emUgaG93IGRpZmZlcmVudCBncm91cHMgb2YgTElCUyBzYW1wbGVzIChjb2xvcmVkIGJ5IG1hdGNoaW5nIFBJWEwgYWJyYXNpb24pIGRpZmZlciBieSBjYXRpb24gY29tcG9zaXRpb24uIERvIGlnbmVvdXMgdnMuIHNlZGltZW50YXJ5IHJvY2sgcGxheSBhIHJvbGwgaW4gY29tcG9zaXRpb24gdGVuZGVuY2llcyBhbmQgc2hvdyBhIHBhdHRlcm4/IEJ5IGxvb2tpbmcgYXQgdGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBzb2lsIGluIGNlcnRhaW4gbG9jYXRpb25zLCB3ZSBjYW4gY29tcGFyZSB0aGUgZGlmZmVyZW5jZXMgaW4gdGhlIFBJWEwgYWJyYXNpb24gYW5kIHJlbGF0aW5nIExJQlMgc2FtcGxlcyBmb3IgYSBjZXJ0YWluIGFyZWEgYnkgY29tYmluaW5nIHRoZSBMSUJTIGFuZCBQSVhMIGRhdGEgc2V0cy4gSW4gb3JkZXIgdG8gYWNjb21wbGlzaCB0aGlzLCB3ZSB3aWxsIHVzZSBhIGRpc3RhbmNlIGZ1bmN0aW9uIHRvIGZpbHRlciB3aXRoaW4gNyBtZXRlcnMgb2YgZGlzdGFuY2UgYmV0d2VlbiBhIFBJWEwgc2FtcGxlIGFuZCBMSUJTIHRhcmdldCAodGhpcyBpcyB0aGUgbWF4aW11bSBkaXN0YW5jZSBvZiBhY2N1cmFjeSBiYXNlZCBvbiBOQVNBJ3MgaW5mb3JtYXRpb24gb24gTElCUyBzcGVjdHJvc2NvcHkgbWFjaGluZXJ5KS4KCiMjIDUuMSBEYXRhLCBDb2RlLCBhbmQgUmVzb3VyY2VzCjEuIHBldGVyY19maW5hbFByb2plY3RGMjQuUm1kICh3aXRoIGtuaXQgcGRmIGFuZCBodG1sKSBpcyB0aGlzIG5vdGVib29rLgpbaHR0cHM6Ly9naXRodWIucnBpLmVkdS9EYXRhSU5DSVRFL0RBUi1NYXJzLUYyNC9ibG9iL21haW4vU3R1ZGVudE5vdGVib29rcy9Bc3NpZ25tZW50MDhfRmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNC5SbWRdKGh0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL1N0dWRlbnROb3RlYm9va3MvQXNzaWdubWVudDA3X0RyYWZ0RmluYWxQcm9qZWN0Tm90ZWJvb2svcGV0ZXJjX2ZpbmFsUHJvamVjdEYyNF9yb3VnaGRyYWZ0LlJtZCkKCjIuIHN1cGVyY2FtX2xpYnNfbW9jX2xvYy5SZHMgd2hpY2ggaXMgdGhlIG9yaWdpbmFsIExJQlMgZGF0YSBnaXZlbiB0byBvdXIgcmVzZWFyY2ggZ3JvdXAuCltodHRwczovL2dpdGh1Yi5ycGkuZWR1L0RhdGFJTkNJVEUvREFSLU1hcnMtRjI0L2Jsb2IvbWFpbi9EYXRhL3N1cGVyY2FtX2xpYnNfbW9jX2xvYy5SZHNdKGh0dHBzOi8vZ2l0aHViLnJwaS5lZHUvRGF0YUlOQ0lURS9EQVItTWFycy1GMjQvYmxvYi9tYWluL0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcykKCgpGaXJzdCwgd2Ugc2V0IGEgZGlzdGFuY2UgdmFyaWFibGUgd2hpY2ggY2FuIGJlIHVzZWQgYXMgYSBzbGlkZXIgYmFyIGluIHRoZSBhcHAuIENoYW5naW5nIHRoaXMgdmFyaWFibGUgc2V0cyB0aGUgbWF4aW11bSBkaXN0YW5jZSBiZXR3ZWVuIGEgUElYTCB0YXJnZXQgYW5kIExJQlMgc2FtcGxlIGZvciB0aGVtIHRvIGJlIGNsYXNzaWZpZWQgdG9nZXRoZXIuCmBgYHtyfQojc2V0IGRpc3RhbmNlIHZhcmlhYmxlIHdoaWNoIGNhbiBiZSB1c2VkIGFzIGEgdG9nZ2xlIHRvb2wKZGlzdGFuY2U9NwpgYGAKClRvIHByZXBhcmUgdGhlIGRhdGEsIEkgc3RhcnQgYnkgbG9hZGluZyBpbiB0aGUgTElCUyBkYXRhLiBUaGVuLCB3ZSBkcm9wIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gY29sdW1ucyBhbmQgc3VtIG9mIHBlcmNlbnRhZ2UgY29sdW1ucyBsZWF2aW5nIHVzIHdpdGgganVzdCB0aGUgd2VpZ2h0ZWQgY29tcG9zaXRpb24gaW4gdGVybXMgb2YgbnVtZXJpY2FsIGRhdGEuIFdlIGFsc28gcmVtb3ZlIHRoZSBzY2N0IHZhbHVlcywgYXMgdGhvc2UgdmFsdWVzIGFyZSB0aGUgb25lcyB0aGF0IGFyZSBlYXJ0aCByZWZlcmVuY2Ugc2FtcGxlcyB0aGF0IFBlcnNlcnZlcmFuY2UgY2FycmllcyB3aXRoIGl0LiBUaGVyZWZvcmUsIHRoZXkgd2lsbCBub3QgYmUgdmVyeSByZWxldmFudCB3aGVuIHBsb3R0aW5nIHRoZSBMSUJTIGRhdGEgYXMgd2UgYXJlIGZvY3VzZWQgb24gdGhlIGNhdGlvbiBjb21iaW5hdGlvbnMgYW5kIHRoZXJlZm9yZSBvbmx5IG5lZWQgdGhlIHdlaWdodGVkIGNvbXBvc2l0aW9ucy4KYGBge3J9CiNMb2FkIGluIExJQlMgZGF0YQpsaWJzLmRmIDwtIHJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvRGF0YS9zdXBlcmNhbV9saWJzX21vY19sb2MuUmRzIikKI0Ryb3AgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBmZWF0dXJlcywgdGhlIHN1bSBvZiB0aGUgcGVyY2VudGFnZXMsIAojdGhlIGRpc3RhbmNlLCBhbmQgdGhlIHRvdGFsIGZyZXF1ZW5jaWVzCmxpYnMuZGYgPC0gbGlicy5kZiAlPiUgCiAgc2VsZWN0KCEoYyhkaXN0YW5jZV9tbSxUb3QuRW0uLFNpTzJfc3RkZXYsVGlPMl9zdGRldixBbDJPM19zdGRldixGZU9UX3N0ZGV2LAogICAgICAgICAgICAgTWdPX3N0ZGV2LE5hMk9fc3RkZXYsQ2FPX3N0ZGV2LEsyT19zdGRldixUb3RhbCkpKQojIENvbnZlcnQgdGhlIHBvaW50cyB0byBudW1lcmljCmxpYnMuZGYkcG9pbnQgPC0gYXMubnVtZXJpYyhsaWJzLmRmJHBvaW50KQpsaWJzLmRmWyw2OjEzXSA8LSBzYXBwbHkobGlicy5kZlssNjoxM10sYXMubnVtZXJpYykKI3JlbW92ZSB0aGUgc2NjdC9yZWZlcmVuY2Ugc2FtcGxlcwpsaWJzLmRmPC1saWJzLmRmJT4lCiAgZmlsdGVyKCEoZ3JlcGwoInNjY3QiLCB0YXJnZXQpKSkKI2FkZCBhIGNvbHVtbiB0byBpbmRpY2F0ZSB0aGUgbmVhcmVzdCBwaXhsCmxpYnMuZGY8LWNiaW5kKG5lYXJlc3RwaXhsPTAsbGlicy5kZikKI21ha2UgYSBkYXRhZnJhbWUgb2YganVzdCB0aGUgTElCUyBMYXQvTG9uZyBhbmQgdGFyZ2V0IG5hbWUgYW5kIHJlbW92ZSBkdXBsaWNhdGVzCmxpYnN0YXJnZXRzLmRmPC1saWJzLmRmWyxjKDEsMyw0LDUpXQpsaWJzdGFyZ2V0cy5kZjwtZGlzdGluY3QobGlic3RhcmdldHMuZGYpCmBgYAoKTmV4dCwgd2Ugd2lsbCBsb2FkIGluIHRoZSBQSVhMIGRhdGEgdGhhdCBpcyBpbiBTdHVkZW50RGF0YSBhcyB0aGUgcGl4bF9zb2xfY29vcmRpbmF0ZXMgZGF0YSBmcmFtZSBpbmNsdWRlcyB0aGUgbGF0aXR1ZGUsIGxvbmdpdHVkZSwgYW5kIHNvbCBvZiBlYWNoIFBJWEwgc2FtcGxlLiBXZSBvbmx5IGluY2x1ZGUgdGhlIG1ldGFkYXRhIGFzIHRoaXMgaXMgYWxsIHRoYXQgaXMgbmVjZXNzYXJ5IGZvciB0aGUgZGlzdGFuY2UgZnVuY3Rpb24gKHRoZSBzYW1wbGUgbmFtZSBhbmQgY29vcmRpbmF0ZXMgb2YgdGhlIHNhbXBsZSkgYXMgd2VsbCBhcyBvbmx5IG9uZSBQSVhMIHNhbXBsZSBmcm9tIGVhY2ggYWJyYXNpb24uIEFzIGVhY2ggYWJyYXNpb24gaGFzIDIgUElYTCBzYW1wbGVzIHRha2VuLCB0aGV5IGhhdmUgdGhlIHNhbWUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBhbmQgdGhlcmVmb3JlIGl0IGlzIHVubmVjZXNzYXJ5IHRvIHVzZSBib3RoLiBXZSBhbHNvIHJlbW92ZSB0aGUgYXRtb3NwaGVyaWMgc2FtcGxlLgpgYGB7cn0KI3JlYWQgaW4gcGl4bCBkYXRhIHdpdGggbGF0L2xvbmcKcGl4bC5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9TdHVkZW50RGF0YS9waXhsX3NvbF9jb29yZGluYXRlcy5SZHMiKQojaW5jbHVkZSBvbmx5IHBpeGwgbWV0YWRhdGEKcGl4bC5kZjwtcGl4bC5kZiAlPiUKICBzZWxlY3QoYygxLDIsMTksMjAsMjIpKQojY29udmVydCBMYXQvTG9uZyB0byBudW1lcmljCnBpeGwuZGYkTGF0IDwtIGFzLm51bWVyaWMocGl4bC5kZiRMYXQpCnBpeGwuZGYkTG9uZyA8LSBhcy5udW1lcmljKHBpeGwuZGYkTG9uZykKI3JlbW92ZSByb3dzIHNvIHdlIG9ubHkgaGF2ZSBvbmUgc2FtcGxlIHBlciBhYnJhc2lvbiBhbmQgcmVtb3ZlIGF0bW9zcGhlcmljIHNhbXBsZQpwaXhsLmRmPC1waXhsLmRmW2MoMiw0LDYsOCwxMCwxMiwxNCwxNiksXQpgYGAKCk5leHQsIHdlIHdpbGwgaW5pdGlhbGl6ZSBhIGRpc3RhbmNlIHZhcmlhYmxlICh0byBpbmRpY2F0ZSBkaXN0YW5jZSBiZXR3ZWVuIFBJWEwgYWJyYXNpb24gYW5kIExJQlMgdGFyZ2V0KSBhbmQgYWxzbyBpbml0aWFsaXplIGVhY2ggUElYTCBhYnJhc2lvbiwgd2hpY2ggd2lsbCBiZSB1c2VkIHRvIG1hcmsgd2hpY2ggUElYTCBhYnJhc2lvbiB0aGUgTElCUyBzYW1wbGUgaXMgY2xvc2VzdCB0byBieSB1c2luZyBhIGZhY3RvciBvZiAwIG9yIDEuIApgYGB7cn0KI0xJQlMgdGFyZ2V0IGRhdGEgZnJhbWUgd2l0aCBkaXN0YW5jZSB2YXJpYWJsZSBhcyB3ZWxsCmxpYnN0YXJnZXRzLmRmPC1jYmluZChsaWJzdGFyZ2V0cy5kZiwiRGlzdGFuY2UiPTAsIkJlbGxlZ3JhZGUiPTAsIkRvdXJiZXMiPTAsIlF1YXJ0aWVyIj0wLCJBbGZhbGZhIj0wLCJUaG9ybnRvbkdhcCI9MCwiQmVycnlIb2xsb3ciPTAsIk5vdmFydXB0YSI9MCwiVWdhbmlrSXNsYW5kIj0wKQpgYGAKClRoZSBkaXN0YW5jZSBmdW5jdGlvbiBiZWxvdyB3aWxsIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIExJQlMgdGFyZ2V0IGFuZCBhbGwgdGhlIFBJWEwgYWJyYXNpb25zLCBhbmQgcGljayB0aGUgc21hbGxlc3QgZGlzdGFuY2UgdG8gcGljayB0aGUgY2xvc2VzdCBQSVhMIGFicmFzaW9uIHRvIHRoYXQgTElCUyB0YXJnZXQuCmBgYHtyfQojRGlzdGFuY2UgZnVuY3Rpb24KZm9yKGkgaW4gMTpucm93KGxpYnN0YXJnZXRzLmRmKSkgewogICAgbGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXTwtYyhkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbOCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpKQogICAgCiAgICBsaWJzdGFyZ2V0cy5kZltpLDFdPC13aGljaC5taW4obGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXSkKICAgIGxpYnN0YXJnZXRzLmRmW2ksNV08LW1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQp9CmxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPC1hcy5mYWN0b3IobGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGwpCmxldmVscyhsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCk8LShjKCJCZWxsZWdyYWRlIiwiRG91cmJlcyIsIlF1YXJ0aWVyIiwiQWxmYWxmYSIsIlRob3JudG9uR2FwIiwiQmVycnlIb2xsb3ciLCJOb3ZhcnVwdGEiLCJVZ2FuaWtJc2xhbmQiKSkKYGBgCgpCZWxvdyBpcyBhbm90aGVyIGluaXRpYWxpemVyIGZvciB0aGUgUElYTCBhYnJhc2lvbiBkYXRhLiBUaGlzIHNldHMgdGhlIHZhcmlhYmxlcyBmb3IgZWFjaCBQSVhMIGFicmFzaW9uIG5hbWUuCmBgYHtyfQojU2V0cyBlYWNoIG5lYXJlc3QgUElYTCB2YXJpYWJsZSBmb3IgZnV0dXJlIHVzZSBpbiBkZWNpZGluZyB3aGljaCB0YXJnZXQgaXMgY2xvc2VzdCB0byBhIExJQlMgc2FtcGxlCkJlbGxlZ3JhZGU8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVsbGVncmFkZSIsXSR0YXJnZXQKRG91cmJlczwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJEb3VyYmVzIixdJHRhcmdldApRdWFydGllcjwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJRdWFydGllciIsXSR0YXJnZXQKQWxmYWxmYTwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJBbGZhbGZhIixdJHRhcmdldApUaG9ybnRvbkdhcDwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJUaG9ybnRvbkdhcCIsXSR0YXJnZXQKQmVycnlIb2xsb3c8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQmVycnlIb2xsb3ciLF0kdGFyZ2V0Ck5vdmFydXB0YTwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJOb3ZhcnVwdGEiLF0kdGFyZ2V0ClVnYW5pa0lzbGFuZDwtbGlic3RhcmdldHMuZGZbbGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGw9PSJVZ2FuaWtJc2xhbmQiLF0kdGFyZ2V0CmBgYAoKTmV4dCwgd2UgZmlsdGVyIG91dCB0aGUgTElCUyB0YXJnZXRzIHRoYXQgYXJlIG5vdCB3aXRoaW4gdGhlIHNwZWNpZmllZCBkaXN0YW5jZSB2YXJpYWJsZS4gVGhlbiwgd2UgbWVyZ2UgdGhlIExJQlMgZGF0YSB3aXRoIHRoZSByZXNwZWN0aXZlIFBJWEwgYWJyYXNpb24gYnkgbXV0YXRpbmcgYW5kIGFkZGluZyBhbiBhYnJhc2lvbiBjb2x1bW4gdGhhdCBoYXMgdGhlIGFicmFzaW9uIG5hbWUgY2xvc2VzdCB0byBlYWNoIExJQlMgdGFyZ2V0LiBXZSBhbHNvIGFkZCBhIGNvbHVtbiwgTElCUyBvciBQSVhMLCB3aGljaCBkZW5vdGVzIGlmIHRoZSByb3cgb2YgZGF0YSBpcyBmcm9tIHRoZSBQSVhMIGFuZCBMSUJTIGRhdGEgc2V0cy4gV2UgYWxzbyBzZXQgdXAgdGhlIGxpYnMudGVybiBtYXRyaXggd2hpY2ggd2lsbCBmb3JtYXQgdGhlIGRhdGEgcHJvcGVybHkgZm9yIHRoZSB0ZXJuYXJ5IHBsb3QuIFRoaXMgZ3JvdXBzIHRoZSBjYXRpb24gY29tcG9zaXRpb25zIGdpdmVuIGJ5IERyLiBSb2dlcnMgdG8gc2V0IHVwIHRoZSB0ZXJuYXJ5IGRpYWdyYW0gYXhlcy4KYGBge3J9CmluY2x1ZGVkLmxpYnM8LShsaWJzdGFyZ2V0cy5kZiU+JQogIGZpbHRlcihEaXN0YW5jZTxtZXRlcnMpKSR0YXJnZXQKbGlicy5tYXRyaXggPC1saWJzLmRmICU+JQogIGZpbHRlcih0YXJnZXQgJWluJSBpbmNsdWRlZC5saWJzKQojc2V0IExJQlMgbWF0cml4IGFuZCB0ZXJuYXJ5IHBsb3QgYnkgYWRkaW5nIGluIGNhdGlvbiBjb21wb25lbnRzIGFuZCBtdXRhdGluZwpsaWJzLm1hdHJpeCA8LSBsaWJzLm1hdHJpeFssYyg1LDc6MTQpXQpsaWJzLnRlcm4gPC0gYXMuZGF0YS5mcmFtZShsaWJzLm1hdHJpeCkgJT4lCiAgbXV0YXRlKHg9KFNpTzIrQWwyTzMpLzEwMCx5PShGZU9UK01nTykvMTAwLHo9KENhTytOYTJPK0syTykvMTAwKSAlPiUKICBzZWxlY3QoLWMoU2lPMixBbDJPMyxGZU9ULE1nTyxDYU8sTmEyTyxLMk8sVGlPMikpCmxpYnMudGVybjwtY2JpbmQoIkFicmFzaW9uIj0wLGxpYnMudGVybikKI1NldCB3aGF0IGFicmFzaW9uIGdvZXMgd2l0aCB0aGUgcmVzcGVjdGl2ZSBMSUJTIHNhbXBsZSBpdCBtYXRjaGVzIHdpdGgKbGlicy50ZXJuPC1saWJzLnRlcm4lPiUKICBtdXRhdGUoQWJyYXNpb24gPSBpZmVsc2UodGFyZ2V0JWluJUFsZmFsZmEsIkFsZmFsZmEiLCAKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgQmVsbGVncmFkZSwgIkJlbGxlZ3JhZGUiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBCZXJyeUhvbGxvdywgIkJlcnJ5SG9sbG93IiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgRG91cmJlcywgIkRvdXJiZXMiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBOb3ZhcnVwdGEsICJOb3ZhcnVwdGEiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBRdWFydGllciwgIlF1YXJ0aWVyIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgVGhvcm50b25HYXAsICJUaG9ybnRvbkdhcCIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFVnYW5pa0lzbGFuZCwgIlVnYW5pa0lzbGFuZCIsQWJyYXNpb24pKSkpKSkpKSkKI3N1bW1hcnkgb2YgTElCUyBkYXRhIGluY2x1ZGluZyBkaXN0YW5jZSBwYXJhbWV0ZXIsIG51bWJlciBvZiBMSUJTIHRhcmdldHMsIGFuZCBudW1iZXIgb2YgTElCUyBwb2ludHMKa2FibGVkZjwtcmJpbmQoIkRpc3RhbmNlIChtKSI9bWV0ZXJzLCJUYXJnZXRzIj1sZW5ndGgoaW5jbHVkZWQubGlicyksIlBvaW50cyI9bnJvdyhsaWJzLnRlcm4pKQprYWJsZShrYWJsZWRmLCBjYXB0aW9uID0iTElCUyAjIG9mIFRhcmdldHMgYW5kIFBvaW50cyB3aXRoaW4gU3BlY2lmaWVkIERpc3RhbmNlIikKYGBgCk5leHQsIHdlIHdpbGwgc2V0IHVwIGEgdGVybmFyeSBkYXRhIGZyYW1lIGZvciB0aGUgUElYTCBkYXRhIHRvIGFkZCBzb21lIHJlZmVyZW5jZSBwb2ludHMgb24gdG9wIG9mIHRoZSBMSUJTIGRhdGEuIFRoaXMgc2hvdWxkIHByb3ZpZGUgbW9yZSBpbnNpZ2h0IGludG8gaG93IHRoZSBjb21wb3NpdGlvbiBvZiBQSVhMIGFuZCBMSUJTIHNhbXBsZXMgcmVsYXRlIGJ5IHRoZWlyIGNhdGlvbiBjb21iaW5hdGlvbnMKCmBgYHtyfQojIFBJWEwgZGF0YSBhZGRlZApwaXhsLmRmIDwtIHJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvRGF0YS9zYW1wbGVzX3BpeGxfd2lkZS5SZHMiKQpwaXhsLmRmW3NhcHBseShwaXhsLmRmLCBpcy5jaGFyYWN0ZXIpXSA8LSBsYXBwbHkocGl4bC5kZltzYXBwbHkocGl4bC5kZiwgaXMuY2hhcmFjdGVyKV0sCmFzLmZhY3RvcikKcGl4bC5kZiA8LSBwaXhsLmRmWzI6MTYsXSAjRXhjbHVkaW5nIGZpcnN0LCBhdG1vc3BoZXJpYyBzYW1wbGUKI1BJWEwgZGF0YSwgd2l0aCBpZGVudGljYWxseSByZWZsZWN0ZWQgY29tcG9zaXRpb25zCm5ld19waXhsX3RyaW0gPC0gcGl4bC5kZiAlPiUKZHBseXI6OnNlbGVjdChjKCJOYTIwIiwiTWdvIiwiQWwyMDMiLCJTaTAyIiwgIksyMCIsIkNhbyIsIkZlTy1UIiwgY2FtcGFpZ24sIHR5cGUpKSAlPiUKcmVuYW1lKCJOYTJPIj0iTmEyMCIsIk1nTyI9Ik1nbyIsIkFsMk8zIj0iQWwyMDMiLCJTaU8yIj0iU2kwMiIsIksyTyI9IksyMCIsCiJDYU8iPSJDYW8iLCJGZU9UIj0iRmVPLVQiKQojdGFrZSB0aGUgc3VtcyBvZiB0aGUgc3BlY2lmaWMgZWxlbWVudHMsIGFuZCByZW5hbWUgdHlwZSBjb2x1bW4KcGl4bF90ZXJuYXJ5IDwtIG5ld19waXhsX3RyaW0gJT4lCm11dGF0ZSh4PShTaU8yK0FsMk8zKS8xMDAseT0oRmVPVCtNZ08pLzEwMCx6PShDYU8rTmEyTytLMk8pLzEwMCwgUElYTF9Sb2NrX1R5cGUgPSB0eXBlKSAlPiUKc2VsZWN0KC1jKFNpTzIsQWwyTzMsRmVPVCxNZ08sQ2FPLE5hMk8sSzJPKSkgJT4lCmRyb3BfbmEoKQojVGhpcyBpcyBmb3IgdGhlIGxhYmVscyBvbiB0aGUgVGVybmFyeSBQbG90IGJlbG93CnBpeGxfdGVybmFyeSA8LSBjYmluZChwaXhsX3Rlcm5hcnksIFNhbXBsZV9kaXNwbGF5PQpjKCIyIiwiMyIsIjQsNiw3IiwiNSw4LDkiLCIiLCIiLCIiLCIiLAoiMTAsMTEiLCIiLCIxMiwxMyIsIiIsIjE0LDE1IiwiIiwiMTYiKSkKYGBgCgoKCiMjIDUuMiBDb250cmlidXRpb24KClRoaXMgd29yayB3YXMgYWxzbyBhIGNvbWJpbmF0aW9uIG9mIE1hcmdvIGFuZCBJLiBUaGUgZGF0YSBzZXQgY3JlYXRpb24gd2FzIGJvdGggb2YgdXMgaW4gb3VyIGJyYWluc3Rvcm1pbmcgYXMgdGhpcyB1dGlsaXplcyB0aGUgZGF0YSBzZXQgd2UgY3JlYXRlZCBvZiBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGZvciBQSVhMLiBUaGUgc2V0dGluZyB1cCBvZiB0aGlzIHBsb3Qgd2FzIGFsc28gY29sbGFib3JhdGl2ZSBiZXR3ZWVuIE1hcmdvIGFuZCBteXNlbGYsIHdlIHdvcmtlZCB0b2dldGhlciB0byBkZWJ1ZyBhbmQgc2V0IHVwIGhvdyB0byBiZXN0IGZvcm1hdCB0aGUgZGF0YSBmb3IgdGhpcyB0ZXJuYXJ5IHBsb3QuIAoKIyMgNS4zIE1ldGhvZHMgRGVzY3JpcHRpb24gCgpGb3IgdGhpcyB0ZXJuYXJ5IHJlcHJlc2VudGF0aW9uLCB3ZSB0b29rIHRoZSB0aW1lIHRvIHJlbW92ZSB0aGUgU0NDVCAoZWFydGggcmVmZXJlbmNlIGRhdGEpIGZyb20gdGhlIExJQlMgZGF0YSwgcmVtb3ZlIHRoZSBhdG1vc3BoZXJpYyBzYW1wbGUgZnJvbSB0aGUgUElYTCBkYXRhLCB1c2UgYSBkaXN0YW5jZSBmdW5jdGlvbiB0byBtYXRjaCBQSVhMIGFicmFzaW9ucyB0byBjb3JyZXNwb25kaW5nIExJQlMgdGFyZ2V0cyB3aXRoaW4gNyBtZXRlcnMgb2YgdGhlIHJlc3BlY3RpdmUgYWJyYXNpb24gKG9yIHdoYXRldmVyIHRoZSBzcGVjaWZpZWQgZGlzdGFuY2UpIGFuZCBzZXQgdXAgYSB0ZXJuYXJ5IGRhdGEgZnJhbWUgd2l0aCBjYXRpb24gY29tYmluYXRpb25zLiBUaGVuLCB0aGUgZGF0YSBmcmFtZSBpcyBtdXRhdGVkIHRvIG1ha2UgdGhlIFBJWEwgYWJyYXNpb25zIGFzIHRoZSBrZXkgKGNvbG9yIExJQlMgdGFyZ2V0cyBieSByZWxhdGVkIFBJWEwgYWJyYXNpb24pIGFuZCBwbG90dGVkIG9uIHRoZSB0ZXJuYXJ5IGRpYWdyYW0uIFdlIGFsc28gcGxvdCB0aGUgUElYTCBzYW1wbGVzIHNvcnRlZCBieSBpZ25lb3VzIG9yIHNlZGltZW50YXJ5IGFzIHN0YXRlZCBieSB0aGUgUElYTCBkYXRhIHNldC4gVGhpcyBjYW4gaGVscCBzaG93IHRoZSBtaW5lcmFsIGV2b2x1dGlvbiBmcm9tIGlnbmVvdXMgdG8gc2VkaW1lbnRhcnkgYW5kIHdoaWNoIFBJWEwgYWJyYXNpb25zIGNvcnJlbGF0ZSB0byB0aGlzLgoKIyMgNS40IFJlc3VsdCBhbmQgRGlzY3Vzc2lvbiAKVXNpbmcgYWxsIG9mIHRoZSBtYW5pcHVsYXRpb24gZG9uZSBmb3IgdGhlIGNyZWF0aW9uIG9mIHRoZSB0ZXJuYXJ5IHBsb3QsIHdlIHRoZW4gcGxvdCB1c2luZyB0aGUgZ2d0ZXJuIGNvbW1hbmQuIFdlIHdpbGwgY29sb3IgYnkgYWJyYXNpb24gdG8gc2VlIHRoZSBkaXN0cmlidXRpb24gb2YgY29tcG9zaXRpb24gYmV0d2VlbiBkaWZmZXJlbnQgYWJyYXNpb25zLiBUaGlzIHNob3VsZCBoZWxwIHVzIGJlIGFibGUgdG8gZHJhdyBkaWZmZXJlbnQgY29uY2x1c2lvbnMgYWJvdXQgaG93IGFicmFzaW9ucyByZWxhdGUgb3IgZG9uJ3QgcmVsYXRlLiBUaGUgbWF4IGRpc3RhbmNlIGJldHdlZW4gdGhlIFBJWEwgdGFyZ2V0IGFuZCBMSUJTIHNhbXBsZSBjYW4gYmUgbW9kaWZpZWQgaG93ZXZlciBkZXNpcmVkLgpgYGB7cn0KZ2d0ZXJuKGxpYnMudGVybiwgZ2d0ZXJuOjphZXMoeD14LHk9eSx6PXopKSArCiAgZ2VvbV9wb2ludChkYXRhPWxpYnMudGVybixhZXMoY29sb3I9QWJyYXNpb24sYWxwaGE9MC41KSkgKyAKICB0aGVtZV9yZ2J3KCkgKyAKICBsYWJzKHRpdGxlPXBhc3RlKCJNYXJzIExJQlMgRGF0YSBXaXRoaW4iLGRpc3RhbmNlLCJtZXRlcnMgb2YgUElYTCIsc2VwPSIgIiksCiAgICAgICB4PSJTaStBbCIsCiAgICAgICB5PSJGZStNZyIsCiAgICAgICB6PSJDYStOYStLIiwKICAgICAgIGNhcHRpb24gPSAiTElCUyBzYW1wbGVzIHRoYXQgYXJlIHdpdGhpbiA3IG1ldGVycyBvZiBhIFBJWEwgYWJyYXNpb24uIFxuRWFjaCBMSUJTIHNhbXBsZSBpcyBjb2xvcmVkIGJ5IHdoYXQgUElYTCBhYnJhc2lvbiBpdCBtYXRjaGVzIHdpdGguIikrCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIsCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwKSAgIyBBbGlnbnMgY2FwdGlvbiB0byB0aGUgbGVmdAogICkgKyAKICBndWlkZXMoYWxwaGE9Im5vbmUiKSsKICBzdXBwcmVzc1dhcm5pbmdzKGdlb21fcG9pbnQoCiAgICBkYXRhPXBpeGxfdGVybmFyeSwgZ2d0ZXJuOjphZXMoY2x1c3Rlcj1QSVhMX1JvY2tfVHlwZSwgc2hhcGU9UElYTF9Sb2NrX1R5cGUpLCBzaXplID0gMikpICsKI0FkZCBsYWJlbHMgdG8gUElYTCBkYXRhIGNvcnJlc3BvbmRpbmcgdG8gc2FtcGxlIG51bWJlcgogIHN1cHByZXNzV2FybmluZ3MoZ2VvbV90ZXh0KGRhdGE9cGl4bF90ZXJuYXJ5LCBnZ3Rlcm46OmFlcyh4PXgsIHk9eSwgej16LCBsYWJlbD1TYW1wbGVfZGlzcGxheSwgY2x1c3Rlcj1QSVhMX1JvY2tfVHlwZSwgICMgSG9yaXpvbnRhbCBhZGp1c3QgdG8gYXZvaWQgb3ZlcmxhcAogICAgaGp1c3QgPSBpZmVsc2UoeCA+IDAuNDMsIDEsIC0wLjEpLAogICAgdmp1c3QgPSBpZmVsc2UoeCA9PSAwLjM2NjgsIDEuMywKICAgICAgICBpZmVsc2UoeCA9PSAwLjM3NSwgMSwgaWZlbHNlKHggPiAwLjQzLCAxLjUsIC0wLjMpKSksCiAgICBmb250ZmFjZT0iYm9sZCIpLAogICAgc2l6ZT0yLjcpKQpgYGAKCgojIyA1LjUgQ29uY2x1c2lvbnMgYW5kIEZ1dHVyZSBXb3JrCkJhc2VkIG9uIHRoaXMgdGVybmFyeSBwbG90LCB3ZSBjYW4gc2VlIEFsZmFsZmEgYW5kIEJlbGxlZ3JhZGUgYXJlIGhpZ2hlciBpbiBTaStBbCBhbmQgVWdhbmlrIElzbGFuZCBpcyBhbiBvdXRsaWVyLiBXZSBjYW4gYWxzbyBzZWUgdGhlIHJvY2sgZXZvbHV0aW9uIGZyb20gaWduZW91cyAoYmxhY2sgY2lyY2xlcykgdG8gc2VkaW1lbnRhcnkgKGJsYWNrIHRyaWFuZ2xlcykgYXMgd2UgbW92ZSBmcm9tIGhpZ2hlciBTaStBbCAob3ZlciA4MCAlKSB0byBsb3cgaW4gU2krQWwgYW5kIGhpZ2ggaW4gRmUrTWcuIFRoaXMgY29uY2x1c2lvbiB3YXMgY29tbWVudGVkIG9uIGJ5IEFuZHJldyBTdGVlbGUgb2YgdGhlIENhcm5lZ2llIEluc3RpdHV0ZSBvZiBTY2llbmNlLiBBcyB0aGlzIHdhcyB0aGUgbGFzdCBwaWVjZSBvZiB0aGUgUElYTCBkYXRhIGluIHRoZSBkYXRhIHNldCBhbmQgaXQgd2FzIG1pc3NpbmcgYSBwYWlyIHNpbmNlIGV2ZXJ5IG90aGVyIGFicmFzaW9uIHdhcyBtYWRlIHVwIG9mIHR3byBzYW1wbGVzLCBpdCBpcyBpbmNsdWRlZCBpbiBoZXJlIGJ1dCB1bnRpbCB0aGUgZGF0YSBzZXQgaXMgdXBkYXRlZCB0aGVyZSBpcyBub3QgZW5vdWdoIGNvbnRleHQgdG8gZXhwbGFpbiB3aHkgaXQgaXMgc28gdmFzdGx5IGRpZmZlcmVudC4gSSB3b3VsZCBhc3N1bWUgaXQgaXMgZHVlIHRvIGhvdyB0aGUgcm9ib3QgaXMgdHJhdmVsaW5nIGFuZCB0aGUgbG9jYXRpb24gb2YgdGhlIFVnYW5payBJc2xhbmQgYWJyYXNpb24gaXMgdmVyeSBkaWZmZXJlbnQgdGhhbiB0aGUgb3RoZXIgNyBhYnJhc2lvbnMuIEZ1dHVyZSB3b3JrIGNvdWxkIGluY2x1ZGUgZGl2aW5nIGRlZXBlciBpbnRvIHRoZSBldm9sdXRpb24gcHJvY2VzcyBvZiByb2NrcyAoaWduZW91cyBhYnJhc2lvbnMgQWxmYWxmYSBhbmQgRG91cmJlcyB0byBzZWRpbWVudGFyeSBhYnJhc2lvbnMgVGhvcm50b24gR2FwKS4KCiMgQmlibGlvZ3JhcGh5CgoqIOKAnE1hcnMgUm9jayBTYW1wbGVzIC0gTkFTQSBTY2llbmNlLuKAnSBOQVNBLCBzY2llbmNlLm5hc2EuZ292L21pc3Npb24vbWFycy0yMDIwLQpwZXJzZXZlcmFuY2UvbWFycy1yb2NrLXNhbXBsZXMvLgoqIOKAnEFuYWx5c3QgTm90ZWJvb2vigJ0sIGh0dHBzOi8vYW4ucnNsLnd1c3RsLmVkdS9tMjAvQU4vYWNjb3VudC9sb2dpbi5hc3B4LiAKCiMgQXBwZW5kaXgKCkhlcmUsIEkgd2lsbCBkaXNwbGF5IHNvbWUgb2YgdGhlIGVhcmxpZXIgc29pbCBjb21wb3NpdGlvbiBwbG90cyBmb3IgZGlmZmVyZW50IFBJWEwgYWJyYXNpb25zLgoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiNFYXJ0aCBxdWFydGlsZXMKZWFydGhxdWFydGlsZXMuZGY8LXJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvRGF0YS9MSUJTX3RyYWluaW5nX3NldF9xdWFydGlsZXMuUmRzIikKI0xvYWQgaW4gTElCUyBkYXRhCmxpYnMuZGYgPC0gcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9EYXRhL3N1cGVyY2FtX2xpYnNfbW9jX2xvYy5SZHMiKQojRHJvcCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGZlYXR1cmVzLCB0aGUgc3VtIG9mIHRoZSBwZXJjZW50YWdlcywgCiN0aGUgZGlzdGFuY2UsIGFuZCB0aGUgdG90YWwgZnJlcXVlbmNpZXMKbGlicy5kZiA8LSBsaWJzLmRmICU+JSAKICBzZWxlY3QoIShjKGRpc3RhbmNlX21tLFRvdC5FbS4sU2lPMl9zdGRldixUaU8yX3N0ZGV2LEFsMk8zX3N0ZGV2LEZlT1Rfc3RkZXYsCiAgICAgICAgICAgICBNZ09fc3RkZXYsTmEyT19zdGRldixDYU9fc3RkZXYsSzJPX3N0ZGV2LFRvdGFsKSkpCiMgQ29udmVydCB0aGUgcG9pbnRzIHRvIG51bWVyaWMKbGlicy5kZiRwb2ludCA8LSBhcy5udW1lcmljKGxpYnMuZGYkcG9pbnQpCmxpYnMuZGZbLDY6MTNdIDwtIHNhcHBseShsaWJzLmRmWyw2OjEzXSxhcy5udW1lcmljKQojcmVtb3ZlIHRoZSBzY2N0L3JlZmVyZW5jZSBzYW1wbGVzCmxpYnMuZGY8LWxpYnMuZGYlPiUKICBmaWx0ZXIoIShncmVwbCgic2NjdCIsIHRhcmdldCkpKQojYWRkIGEgY29sdW1uIHRvIGluZGljYXRlIHRoZSBuZWFyZXN0IHBpeGwKbGlicy5kZjwtY2JpbmQobmVhcmVzdHBpeGw9MCxsaWJzLmRmKQojbWFrZSBhIGRhdGFmcmFtZSBvZiBqdXN0IHRoZSBMSUJTIExhdC9Mb25nIGFuZCB0YXJnZXQgbmFtZSBhbmQgcmVtb3ZlIGR1cGxpY2F0ZXMKbGlic3RhcmdldHMuZGY8LWxpYnMuZGZbLGMoMSwzLDQsNSldCmxpYnN0YXJnZXRzLmRmPC1kaXN0aW5jdChsaWJzdGFyZ2V0cy5kZikKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI0Nob29zZSBtYXggZGlzdGFuY2UgdmFyaWFibGUgYmV0d2VlbiBQSVhMIGFuZCBMSUJTIGRhdGEKbWV0ZXJzID0gNwojQ2hvb3NlIFBJWEwgYWJyYXNpb24geW91IHdhbnQgdG8gbG9vayBhdAphYnJhc2lvbl9uYW1lID0gIkFsZmFsZmEiCmBgYAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiNyZWFkIGluIHBpeGwgZGF0YSB3aXRoIGxhdC9sb25nCnBpeGwuZGY8LXJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvU3R1ZGVudERhdGEvcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzIikKI2luY2x1ZGUgb25seSBwaXhsIG1ldGFkYXRhCnBpeGwuZGY8LXBpeGwuZGYgJT4lCiAgc2VsZWN0KGMoMSwyLDE5LDIwLDIyKSkKI2NvbnZlcnQgTGF0L0xvbmcgdG8gbnVtZXJpYwpwaXhsLmRmJExhdCA8LSBhcy5udW1lcmljKHBpeGwuZGYkTGF0KQpwaXhsLmRmJExvbmcgPC0gYXMubnVtZXJpYyhwaXhsLmRmJExvbmcpCiNyZW1vdmUgcm93cyBzbyB3ZSBvbmx5IGhhdmUgb25lIHNhbXBsZSBwZXIgYWJyYXNpb24gYW5kIHJlbW92ZSBhdG1vc3BoZXJpYyBzYW1wbGUKcGl4bC5kZjwtcGl4bC5kZltjKDIsNCw2LDgsMTAsMTIsMTQsMTYpLF0KYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KbGlic3RhcmdldHMuZGY8LWNiaW5kKGxpYnN0YXJnZXRzLmRmLCJEaXN0YW5jZSI9MCwiQmVsbGVncmFkZSI9MCwiRG91cmJlcyI9MCwiUXVhcnRpZXIiPTAsIkFsZmFsZmEiPTAsIlRob3JudG9uR2FwIj0wLCJCZXJyeSBIb2xsb3ciPTAsIk5vdmFydXB0YSI9MCwiVWdhbmlrIElzbGFuZCI9MCkKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KZm9yKGkgaW4gMTpucm93KGxpYnN0YXJnZXRzLmRmKSkgewogICAgbGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXTwtYyhkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbOCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpKQogICAgCiAgICBsaWJzdGFyZ2V0cy5kZltpLDFdPC13aGljaC5taW4obGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXSkKICAgIGxpYnN0YXJnZXRzLmRmW2ksNV08LW1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQp9CmxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPC1hcy5mYWN0b3IobGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGwpCmxldmVscyhsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCk8LShjKCJCZWxsZWdyYWRlIiwiRG91cmJlcyIsIlF1YXJ0aWVyIiwiQWxmYWxmYSIsIlRob3JudG9uR2FwIiwiQmVycnkgSG9sbG93IiwiTm92YXJ1cHRhIiwiVWdhbmlrIElzbGFuZCIpKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpCZWxsZWdyYWRlPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlbGxlZ3JhZGUiLF0kdGFyZ2V0CkRvdXJiZXM8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iRG91cmJlcyIsXSR0YXJnZXQKUXVhcnRpZXI8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iUXVhcnRpZXIiLF0kdGFyZ2V0CkFsZmFsZmE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQWxmYWxmYSIsXSR0YXJnZXQKVGhvcm50b25HYXA8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVGhvcm50b25HYXAiLF0kdGFyZ2V0CkJlcnJ5SG9sbG93PC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlcnJ5IEhvbGxvdyIsXSR0YXJnZXQKTm92YXJ1cHRhPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09Ik5vdmFydXB0YSIsXSR0YXJnZXQKVWdhbmlrSXNsYW5kPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IlVnYW5payBJc2xhbmQiLF0kdGFyZ2V0CmBgYAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CmluY2x1ZGVkLmxpYnM8LShsaWJzdGFyZ2V0cy5kZiU+JQogIGZpbHRlcihEaXN0YW5jZTxtZXRlcnMpKSR0YXJnZXQKbGlicy5tYXRyaXggPC1saWJzLmRmICU+JQogIGZpbHRlcih0YXJnZXQgJWluJSBpbmNsdWRlZC5saWJzKQpsaWJzLm1hdHJpeCA8LSBsaWJzLm1hdHJpeFssYyg1LDc6MTQpXQpsaWJzLm1hdHJpeDwtbGlicy5tYXRyaXhbLGMoMToyLDQ6OSwzKV0KbGlicy5tYXRyaXg8LWNiaW5kKCJBYnJhc2lvbiI9MCxsaWJzLm1hdHJpeCkKbGlicy5tYXRyaXg8LWxpYnMubWF0cml4JT4lCiAgbXV0YXRlKEFicmFzaW9uID0gaWZlbHNlKHRhcmdldCVpbiVBbGZhbGZhLCJBbGZhbGZhIiwgCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIEJlbGxlZ3JhZGUsICJCZWxsZWdyYWRlIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgQmVycnlIb2xsb3csICJCZXJyeSBIb2xsb3ciLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBEb3VyYmVzLCAiRG91cmJlcyIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIE5vdmFydXB0YSwgIk5vdmFydXB0YSIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFF1YXJ0aWVyLCAiUXVhcnRpZXIiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBUaG9ybnRvbkdhcCwgIlRob3JudG9uR2FwIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgVWdhbmlrSXNsYW5kLCAiVWdhbmlrIElzbGFuZCIsQWJyYXNpb24pKSkpKSkpKSkKbGlicy5tYXRyaXg8LWNiaW5kKGxpYnNvcnBpeGw9MSxsaWJzLm1hdHJpeCkKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI3JlYWQgaW4gcGl4bCBkYXRhIHdpdGggbGF0L2xvbmcKcGl4bC5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9TdHVkZW50RGF0YS9waXhsX3NvbF9jb29yZGluYXRlcy5SZHMiKQpwaXhsLmRmPC1waXhsLmRmICU+JQogIHNlbGVjdChjKDU6OCwxMjoxNCwxNywxOSwxOCwyMikpCiNyZW9yZGVyIHBpeGwgY29sdW1ucyBzbyB0aGF0IGl0IG1hdGNoZXMgbGlicyBkYXRhIG9yZ2FuaXphdGlvbgpwaXhsLmRmPC1waXhsLmRmWyxjKDExLDEwLDQsMyw4LDIsNiwxLDUsNyldCiNyZW1vdmUgYXRtb3NwaGVyaWMgc2FtcGxlCnBpeGwuZGY8LXBpeGwuZGZbMjoxNixdCnBpeGwuZGY8LWNiaW5kKGxpYnNvcnBpeGw9MCxwaXhsLmRmKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpjb2xuYW1lcyhwaXhsLmRmKTwtY29sbmFtZXMobGlicy5tYXRyaXgpCnBpeGxsaWJzLmRmPC1yYmluZChwaXhsLmRmLGxpYnMubWF0cml4KQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIEVhcnRoIHF1YXJ0aWxlcwpmaWx0ZXJlZF9yb3dzIDwtIGVhcnRocXVhcnRpbGVzLmRmICU+JQogIGZpbHRlcihgVHJhaW5pbmcgc2V0IFF1YXJ0aWxlc2AgJWluJSBjKCIxc3QiLCAiM3JkIiwgIk1lZCIpKQplYXJ0aHF1YXJ0aWxlc19sb25nIDwtIGZpbHRlcmVkX3Jvd3MgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiU2lPMiIpOmxhc3RfY29sKCksIG5hbWVzX3RvID0gIkNvbXBvdW5kIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2UiKQoKZWFydGhxdWFydGlsZXNfbG9uZyA8LSBlYXJ0aHF1YXJ0aWxlc19sb25nICU+JSByZW5hbWUoUXVhcnRpbGVzID0gYFRyYWluaW5nIHNldCBRdWFydGlsZXNgKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIEZpbHRlciBmb3IgdGhlIHNwZWNpZmljIGFicmFzaW9uIHNhbXBsZSwgZS5nLiwgIkFsZmFsZmEiCnBpeGxsaWJzX2ZpbHRlcmVkIDwtIHBpeGxsaWJzLmRmICU+JQogIGZpbHRlcihBYnJhc2lvbiA9PSBhYnJhc2lvbl9uYW1lKQoKIyBQaXZvdCB0aGUgZGF0YSB0byBsb25nZXIgZm9ybWF0IGZvciBnZ3Bsb3QKcGl4bGxpYnNfbG9uZyA8LSBwaXhsbGlic19maWx0ZXJlZCAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJTaU8yIik6bGFzdF9jb2woKSwgbmFtZXNfdG8gPSAiQ29tcG91bmQiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSIpCgpkZXNpcmVkX29yZGVyIDwtIGMoIlNpTzIiLCAiQWwyTzMiLCAiRmVPVCIsICJNZ08iLCAiQ2FPIiwgIk5hMk8iLCAiSzJPIiwgIlRpTzIiKSAgIyBTcGVjaWZ5IHlvdXIgY3VzdG9tIG9yZGVyIGhlcmUKcGl4bGxpYnNfbG9uZyRDb21wb3VuZCA8LSBmYWN0b3IocGl4bGxpYnNfbG9uZyRDb21wb3VuZCwgbGV2ZWxzID0gZGVzaXJlZF9vcmRlcikKYGBgCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQojIE1hcCB0aGUgUElYTC9MSUJTIGNvbHVtbiB0byBjb2xvciBhbmQgdXNlIHRhcmdldF9uYW1lIHRvIGRpZmZlcmVudGlhdGUgbGluZXMKc3VwcHJlc3NXYXJuaW5ncyhnZ3Bsb3QocGl4bGxpYnNfbG9uZywgYWVzKHggPSBDb21wb3VuZCwgeSA9IFBlcmNlbnRhZ2UsIGNvbG9yID0gYXMuZmFjdG9yKGxpYnNvcnBpeGwpLCBncm91cCA9IHRhcmdldCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogICMgQWRkIEVhcnRoIHF1YXJ0aWxlIGxpbmVzIHVzaW5nIGVhcnRocXVhcnRpbGVzX2xvbmcKICBnZW9tX2xpbmUoZGF0YSA9IGVhcnRocXVhcnRpbGVzX2xvbmcsIGFlcyh4ID0gQ29tcG91bmQsIHkgPSBQZXJjZW50YWdlLCBsaW5ldHlwZSA9IFF1YXJ0aWxlcywgZ3JvdXAgPSBRdWFydGlsZXMpLCAKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTb2lsIENvbXBvc2l0aW9uIGZvciBQSVhMIixhYnJhc2lvbl9uYW1lLCJhbmQgTElCUyB3aXRoaW4iLCBtZXRlcnMsICJtZXRlcnMiLCBzZXAgPSAiICIpLAogICAgICAgeCA9ICJDaGVtaWNhbCBDb21wb3VuZCIsCiAgICAgICB5ID0gIldlaWdodCBQZXJjZW50YWdlIiwKICAgICAgIGNvbG9yID0gIk1lYXN1cmVtZW50IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiUXVhcnRpbGVzIiwKICAgICAgIGNhcHRpb24gPSAiVGhlIGNoZW1pY2FsIGNvbXBvc2l0aW9uIG9mIGEgUElYTCBhYnJhc2lvbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyB0YXJnZXRzIFxuIHdpdGhpbiBzcGVjaWZpZWQgZGlzdGFuY2Ugb2YgcmVzcGVjdGl2ZSBhYnJhc2lvbi4iKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImJsdWUiLCAiMSIgPSAicmVkIiksIGxhYmVscyA9IGMoIlBJWEwiLCAiTElCUyIpKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNSwgeSA9IC41MCwgbGFiZWwgPSAiMXN0IFF1YXJ0aWxlIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMiwgbGFiZWwgPSAiTWVkaWFuIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMTAsIGxhYmVsID0gIjNyZCBRdWFydGlsZSIsIGNvbG9yID0gImJsYWNrIiwgaGp1c3QgPSAwKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgICAgIyBDZW50ZXIgdGhlIGNhcHRpb24gb24gdGhlIGxlZnQgc2lkZQogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkgICMgQWxpZ25zIGNhcHRpb24gdG8gdGhlIGxlZnQKICApKQoKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI0VhcnRoIHF1YXJ0aWxlcwplYXJ0aHF1YXJ0aWxlcy5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9EYXRhL0xJQlNfdHJhaW5pbmdfc2V0X3F1YXJ0aWxlcy5SZHMiKQojTG9hZCBpbiBMSUJTIGRhdGEKbGlicy5kZiA8LSByZWFkUkRTKCIvYWNhZGVtaWNzL01BVFAtNDkxMC1GMjQvREFSLU1hcnMtRjI0L0RhdGEvc3VwZXJjYW1fbGlic19tb2NfbG9jLlJkcyIpCiNEcm9wIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gZmVhdHVyZXMsIHRoZSBzdW0gb2YgdGhlIHBlcmNlbnRhZ2VzLCAKI3RoZSBkaXN0YW5jZSwgYW5kIHRoZSB0b3RhbCBmcmVxdWVuY2llcwpsaWJzLmRmIDwtIGxpYnMuZGYgJT4lIAogIHNlbGVjdCghKGMoZGlzdGFuY2VfbW0sVG90LkVtLixTaU8yX3N0ZGV2LFRpTzJfc3RkZXYsQWwyTzNfc3RkZXYsRmVPVF9zdGRldiwKICAgICAgICAgICAgIE1nT19zdGRldixOYTJPX3N0ZGV2LENhT19zdGRldixLMk9fc3RkZXYsVG90YWwpKSkKIyBDb252ZXJ0IHRoZSBwb2ludHMgdG8gbnVtZXJpYwpsaWJzLmRmJHBvaW50IDwtIGFzLm51bWVyaWMobGlicy5kZiRwb2ludCkKbGlicy5kZlssNjoxM10gPC0gc2FwcGx5KGxpYnMuZGZbLDY6MTNdLGFzLm51bWVyaWMpCiNyZW1vdmUgdGhlIHNjY3QvcmVmZXJlbmNlIHNhbXBsZXMKbGlicy5kZjwtbGlicy5kZiU+JQogIGZpbHRlcighKGdyZXBsKCJzY2N0IiwgdGFyZ2V0KSkpCiNhZGQgYSBjb2x1bW4gdG8gaW5kaWNhdGUgdGhlIG5lYXJlc3QgcGl4bApsaWJzLmRmPC1jYmluZChuZWFyZXN0cGl4bD0wLGxpYnMuZGYpCiNtYWtlIGEgZGF0YWZyYW1lIG9mIGp1c3QgdGhlIExJQlMgTGF0L0xvbmcgYW5kIHRhcmdldCBuYW1lIGFuZCByZW1vdmUgZHVwbGljYXRlcwpsaWJzdGFyZ2V0cy5kZjwtbGlicy5kZlssYygxLDMsNCw1KV0KbGlic3RhcmdldHMuZGY8LWRpc3RpbmN0KGxpYnN0YXJnZXRzLmRmKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojQ2hvb3NlIG1heCBkaXN0YW5jZSB2YXJpYWJsZSBiZXR3ZWVuIFBJWEwgYW5kIExJQlMgZGF0YQptZXRlcnMgPSA3CiNDaG9vc2UgUElYTCBhYnJhc2lvbiB5b3Ugd2FudCB0byBsb29rIGF0CmFicmFzaW9uX25hbWUgPSAiUXVhcnRpZXIiCmBgYAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CiNyZWFkIGluIHBpeGwgZGF0YSB3aXRoIGxhdC9sb25nCnBpeGwuZGY8LXJlYWRSRFMoIi9hY2FkZW1pY3MvTUFUUC00OTEwLUYyNC9EQVItTWFycy1GMjQvU3R1ZGVudERhdGEvcGl4bF9zb2xfY29vcmRpbmF0ZXMuUmRzIikKI2luY2x1ZGUgb25seSBwaXhsIG1ldGFkYXRhCnBpeGwuZGY8LXBpeGwuZGYgJT4lCiAgc2VsZWN0KGMoMSwyLDE5LDIwLDIyKSkKI2NvbnZlcnQgTGF0L0xvbmcgdG8gbnVtZXJpYwpwaXhsLmRmJExhdCA8LSBhcy5udW1lcmljKHBpeGwuZGYkTGF0KQpwaXhsLmRmJExvbmcgPC0gYXMubnVtZXJpYyhwaXhsLmRmJExvbmcpCiNyZW1vdmUgcm93cyBzbyB3ZSBvbmx5IGhhdmUgb25lIHNhbXBsZSBwZXIgYWJyYXNpb24gYW5kIHJlbW92ZSBhdG1vc3BoZXJpYyBzYW1wbGUKcGl4bC5kZjwtcGl4bC5kZltjKDIsNCw2LDgsMTAsMTIsMTQsMTYpLF0KYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KbGlic3RhcmdldHMuZGY8LWNiaW5kKGxpYnN0YXJnZXRzLmRmLCJEaXN0YW5jZSI9MCwiQmVsbGVncmFkZSI9MCwiRG91cmJlcyI9MCwiUXVhcnRpZXIiPTAsIkFsZmFsZmEiPTAsIlRob3JudG9uR2FwIj0wLCJCZXJyeSBIb2xsb3ciPTAsIk5vdmFydXB0YSI9MCwiVWdhbmlrIElzbGFuZCI9MCkKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KZm9yKGkgaW4gMTpucm93KGxpYnN0YXJnZXRzLmRmKSkgewogICAgbGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXTwtYyhkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbMyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNSxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNixjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbNyxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXN0SGF2ZXJzaW5lKHBpeGwuZGZbOCxjKDEsMildLGxpYnN0YXJnZXRzLmRmW2ksYygyLDMpXSxyPTMzOTMxNjkpKQogICAgCiAgICBsaWJzdGFyZ2V0cy5kZltpLDFdPC13aGljaC5taW4obGlic3RhcmdldHMuZGZbaSxjKDY6MTMpXSkKICAgIGxpYnN0YXJnZXRzLmRmW2ksNV08LW1pbihsaWJzdGFyZ2V0cy5kZltpLGMoNjoxMyldKQp9CmxpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPC1hcy5mYWN0b3IobGlic3RhcmdldHMuZGYkbmVhcmVzdHBpeGwpCmxldmVscyhsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bCk8LShjKCJCZWxsZWdyYWRlIiwiRG91cmJlcyIsIlF1YXJ0aWVyIiwiQWxmYWxmYSIsIlRob3JudG9uR2FwIiwiQmVycnkgSG9sbG93IiwiTm92YXJ1cHRhIiwiVWdhbmlrIElzbGFuZCIpKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpCZWxsZWdyYWRlPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlbGxlZ3JhZGUiLF0kdGFyZ2V0CkRvdXJiZXM8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iRG91cmJlcyIsXSR0YXJnZXQKUXVhcnRpZXI8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iUXVhcnRpZXIiLF0kdGFyZ2V0CkFsZmFsZmE8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iQWxmYWxmYSIsXSR0YXJnZXQKVGhvcm50b25HYXA8LWxpYnN0YXJnZXRzLmRmW2xpYnN0YXJnZXRzLmRmJG5lYXJlc3RwaXhsPT0iVGhvcm50b25HYXAiLF0kdGFyZ2V0CkJlcnJ5SG9sbG93PC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IkJlcnJ5IEhvbGxvdyIsXSR0YXJnZXQKTm92YXJ1cHRhPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09Ik5vdmFydXB0YSIsXSR0YXJnZXQKVWdhbmlrSXNsYW5kPC1saWJzdGFyZ2V0cy5kZltsaWJzdGFyZ2V0cy5kZiRuZWFyZXN0cGl4bD09IlVnYW5payBJc2xhbmQiLF0kdGFyZ2V0CmBgYAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CmluY2x1ZGVkLmxpYnM8LShsaWJzdGFyZ2V0cy5kZiU+JQogIGZpbHRlcihEaXN0YW5jZTxtZXRlcnMpKSR0YXJnZXQKbGlicy5tYXRyaXggPC1saWJzLmRmICU+JQogIGZpbHRlcih0YXJnZXQgJWluJSBpbmNsdWRlZC5saWJzKQpsaWJzLm1hdHJpeCA8LSBsaWJzLm1hdHJpeFssYyg1LDc6MTQpXQpsaWJzLm1hdHJpeDwtbGlicy5tYXRyaXhbLGMoMToyLDQ6OSwzKV0KbGlicy5tYXRyaXg8LWNiaW5kKCJBYnJhc2lvbiI9MCxsaWJzLm1hdHJpeCkKbGlicy5tYXRyaXg8LWxpYnMubWF0cml4JT4lCiAgbXV0YXRlKEFicmFzaW9uID0gaWZlbHNlKHRhcmdldCVpbiVBbGZhbGZhLCJBbGZhbGZhIiwgCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIEJlbGxlZ3JhZGUsICJCZWxsZWdyYWRlIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgQmVycnlIb2xsb3csICJCZXJyeSBIb2xsb3ciLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBEb3VyYmVzLCAiRG91cmJlcyIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIE5vdmFydXB0YSwgIk5vdmFydXB0YSIsCiAgICAgICAgICAgICAgICAgICAgaWZlbHNlKHRhcmdldCAlaW4lIFF1YXJ0aWVyLCAiUXVhcnRpZXIiLAogICAgICAgICAgICAgICAgICAgIGlmZWxzZSh0YXJnZXQgJWluJSBUaG9ybnRvbkdhcCwgIlRob3JudG9uR2FwIiwKICAgICAgICAgICAgICAgICAgICBpZmVsc2UodGFyZ2V0ICVpbiUgVWdhbmlrSXNsYW5kLCAiVWdhbmlrIElzbGFuZCIsQWJyYXNpb24pKSkpKSkpKSkKbGlicy5tYXRyaXg8LWNiaW5kKGxpYnNvcnBpeGw9MSxsaWJzLm1hdHJpeCkKYGBgCgpgYGB7ciwgaW5jbHVkZT1GQUxTRX0KI3JlYWQgaW4gcGl4bCBkYXRhIHdpdGggbGF0L2xvbmcKcGl4bC5kZjwtcmVhZFJEUygiL2FjYWRlbWljcy9NQVRQLTQ5MTAtRjI0L0RBUi1NYXJzLUYyNC9TdHVkZW50RGF0YS9waXhsX3NvbF9jb29yZGluYXRlcy5SZHMiKQpwaXhsLmRmPC1waXhsLmRmICU+JQogIHNlbGVjdChjKDU6OCwxMjoxNCwxNywxOSwxOCwyMikpCiNyZW9yZGVyIHBpeGwgY29sdW1ucyBzbyB0aGF0IGl0IG1hdGNoZXMgbGlicyBkYXRhIG9yZ2FuaXphdGlvbgpwaXhsLmRmPC1waXhsLmRmWyxjKDExLDEwLDQsMyw4LDIsNiwxLDUsNyldCiNyZW1vdmUgYXRtb3NwaGVyaWMgc2FtcGxlCnBpeGwuZGY8LXBpeGwuZGZbMjoxNixdCnBpeGwuZGY8LWNiaW5kKGxpYnNvcnBpeGw9MCxwaXhsLmRmKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQpjb2xuYW1lcyhwaXhsLmRmKTwtY29sbmFtZXMobGlicy5tYXRyaXgpCnBpeGxsaWJzLmRmPC1yYmluZChwaXhsLmRmLGxpYnMubWF0cml4KQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIEVhcnRoIHF1YXJ0aWxlcwpmaWx0ZXJlZF9yb3dzIDwtIGVhcnRocXVhcnRpbGVzLmRmICU+JQogIGZpbHRlcihgVHJhaW5pbmcgc2V0IFF1YXJ0aWxlc2AgJWluJSBjKCIxc3QiLCAiM3JkIiwgIk1lZCIpKQplYXJ0aHF1YXJ0aWxlc19sb25nIDwtIGZpbHRlcmVkX3Jvd3MgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBzdGFydHNfd2l0aCgiU2lPMiIpOmxhc3RfY29sKCksIG5hbWVzX3RvID0gIkNvbXBvdW5kIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2UiKQoKZWFydGhxdWFydGlsZXNfbG9uZyA8LSBlYXJ0aHF1YXJ0aWxlc19sb25nICU+JSByZW5hbWUoUXVhcnRpbGVzID0gYFRyYWluaW5nIHNldCBRdWFydGlsZXNgKQpgYGAKCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQojIEZpbHRlciBmb3IgdGhlIHNwZWNpZmljIGFicmFzaW9uIHNhbXBsZSwgZS5nLiwgIkFsZmFsZmEiCnBpeGxsaWJzX2ZpbHRlcmVkIDwtIHBpeGxsaWJzLmRmICU+JQogIGZpbHRlcihBYnJhc2lvbiA9PSBhYnJhc2lvbl9uYW1lKQoKIyBQaXZvdCB0aGUgZGF0YSB0byBsb25nZXIgZm9ybWF0IGZvciBnZ3Bsb3QKcGl4bGxpYnNfbG9uZyA8LSBwaXhsbGlic19maWx0ZXJlZCAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXJ0c193aXRoKCJTaU8yIik6bGFzdF9jb2woKSwgbmFtZXNfdG8gPSAiQ29tcG91bmQiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSIpCgpkZXNpcmVkX29yZGVyIDwtIGMoIlNpTzIiLCAiQWwyTzMiLCAiRmVPVCIsICJNZ08iLCAiQ2FPIiwgIk5hMk8iLCAiSzJPIiwgIlRpTzIiKSAgIyBTcGVjaWZ5IHlvdXIgY3VzdG9tIG9yZGVyIGhlcmUKcGl4bGxpYnNfbG9uZyRDb21wb3VuZCA8LSBmYWN0b3IocGl4bGxpYnNfbG9uZyRDb21wb3VuZCwgbGV2ZWxzID0gZGVzaXJlZF9vcmRlcikKYGBgCgpgYGB7ciwgaW5jbHVkZT1UUlVFfQojIE1hcCB0aGUgUElYTC9MSUJTIGNvbHVtbiB0byBjb2xvciBhbmQgdXNlIHRhcmdldF9uYW1lIHRvIGRpZmZlcmVudGlhdGUgbGluZXMKc3VwcHJlc3NXYXJuaW5ncyhnZ3Bsb3QocGl4bGxpYnNfbG9uZywgYWVzKHggPSBDb21wb3VuZCwgeSA9IFBlcmNlbnRhZ2UsIGNvbG9yID0gYXMuZmFjdG9yKGxpYnNvcnBpeGwpLCBncm91cCA9IHRhcmdldCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnM9J2xvZzEwJykgKwogICMgQWRkIEVhcnRoIHF1YXJ0aWxlIGxpbmVzIHVzaW5nIGVhcnRocXVhcnRpbGVzX2xvbmcKICBnZW9tX2xpbmUoZGF0YSA9IGVhcnRocXVhcnRpbGVzX2xvbmcsIGFlcyh4ID0gQ29tcG91bmQsIHkgPSBQZXJjZW50YWdlLCBsaW5ldHlwZSA9IFF1YXJ0aWxlcywgZ3JvdXAgPSBRdWFydGlsZXMpLCAKICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJTb2lsIENvbXBvc2l0aW9uIGZvciBQSVhMIixhYnJhc2lvbl9uYW1lLCJhbmQgTElCUyB3aXRoaW4iLCBtZXRlcnMsICJtZXRlcnMiLCBzZXAgPSAiICIpLAogICAgICAgeCA9ICJDaGVtaWNhbCBDb21wb3VuZCIsCiAgICAgICB5ID0gIldlaWdodCBQZXJjZW50YWdlIiwKICAgICAgIGNvbG9yID0gIk1lYXN1cmVtZW50IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiUXVhcnRpbGVzIiwKICAgICAgIGNhcHRpb24gPSAiVGhlIGNoZW1pY2FsIGNvbXBvc2l0aW9uIG9mIGEgUElYTCBhYnJhc2lvbiBhbmQgdGhlIGNvcnJlc3BvbmRpbmcgTElCUyB0YXJnZXRzIFxuIHdpdGhpbiBzcGVjaWZpZWQgZGlzdGFuY2Ugb2YgcmVzcGVjdGl2ZSBhYnJhc2lvbi4iKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImJsdWUiLCAiMSIgPSAicmVkIiksIGxhYmVscyA9IGMoIlBJWEwiLCAiTElCUyIpKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNSwgeSA9IC41MCwgbGFiZWwgPSAiMXN0IFF1YXJ0aWxlIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMiwgbGFiZWwgPSAiTWVkaWFuIiwgY29sb3IgPSAiYmxhY2siLCBoanVzdCA9IDApICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LCB5ID0gMTAsIGxhYmVsID0gIjNyZCBRdWFydGlsZSIsIGNvbG9yID0gImJsYWNrIiwgaGp1c3QgPSAwKSsKICB0aGVtZV9taW5pbWFsKCkrCiAgICAgIyBDZW50ZXIgdGhlIGNhcHRpb24gb24gdGhlIGxlZnQgc2lkZQogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCkgICMgQWxpZ25zIGNhcHRpb24gdG8gdGhlIGxlZnQKICApKQoKYGBgCg==
diff --git a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.pdf b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.pdf index 52ddbac..f223108 100644 Binary files a/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.pdf and b/StudentNotebooks/Assignment08_FinalProjectNotebook/peterc_finalProjectF24.pdf differ