Abstract

This project reports a methodological advancement on how topic modeling can be used to analyze qualitative data from transcripts of focus groups conducted with participants in an international professional development program. The program is designed to prepare inservice educators for culturally-responsive teaching (CRT) through practice with the development of technical representations of cultural themes in an international context. Themes developed using topic modeling can be compared to existing thematic analysis conducted by researchers on the same data. This will provide insight into the strengths and weaknesses of each approach and demonstrate the potential of topic modeling to enhance qualitative data analysis. This will be useful for future researchers interested in the interaction between qualitative methodology and topic modeling.


1. PREPARE

1a. Data sources used for text analysis

Context: Professional Development Abroad

The data are from an ongoing, international, professional development program for inservice teachers. It includes three Saturday classes in the spring, two weeks of a study abroad program in the summer to an international destination (in 2022, to Munich Germany) and one follow up session in the fall. In this professional development abroad, teachers build a portfolio that represents a chosen cultural theme, including a lesson plan illustrating how they plan to apply technical cultural representation and/or analysis in their own classrooms. The program aims to provide teachers with experiences practicing with cultural frames and representational tools, so they can work with their own students to elicit and represent diverse cultural identities and perspectives.

Data Collection and Analysis

First, using qualitative methods, the research team analyzed data collected during focus groups, from digital portfolios, and from observations during the professional development program. Data collected consisted of researcher memos, projects and artifacts created by 19 teachers, and post-reflective focus groups after the professional development experience. Using the transcripts from the focus groups, participants’ portfolios, and researcher observations, Braun and Clarke’s (2022) process of reflexive thematic analysis to analyze focus group data was used. 

Initial findings from thematic analysis of focus group data indicated that

1.) Self-selected digital projects allowed participants to develop professional knowledge related to their specific teaching content, curriculum, and classroom;

2.) International immersive experience with targeted professional development provided an opportunity for reflections on pandemic/post-pandemic instruction; and

3.) Teachers reflected that the experience had an impact on their teaching dispositions and plans for the future.

This project will outline a second step in this process, in which the same data will be analyzed using topic modeling. Topic modeling is a machine learning technique that automatically analyzes text data to determine cluster words for a set of documents. This is known as ‘unsupervised’ machine learning because it doesn’t require a predefined list of tags or training data that’s been previously classified by humans. This additional step in analyzing the data advances the field of qualitative research as it offers a means of reflecting on the comparison of the two sets of results.

1b. Guiding Question

With the increasing amount of qualitative data being generated in research studies, it is essential to have effective methods for analyzing and interpreting this information. The use of topic modeling in the analysis of textual data has gained popularity in recent years due to its ability to identify hidden themes and patterns within large datasets. This project describes a potential methodological advancement on how topic modeling can be used to analyze qualitative data.

Thus, the primary research question is:

What does topic modeling in the analysis of textual data from focus groups with inservice teachers participating in international professional development reveal about how topic modeling can enhance qualitative research data?

2. WRANGLE

To analyze the textual data using topic modeling, the workflow of the process will include data wrangling, modeling, and exploration as follows: 

The data will be wrangled, a process which involves some combination of cleaning, reshaping, transforming, and merging data (Wickham & Grolemund, 2017). The text will be preprocessed, including converting the data into a tidy text format. This includes data tokenization, removal of stop words, and stemming.

The text will then be analyzed by fitting a topic modeling algorithm using Latent Dirichlet Allocation (LDA). Then beta values were created to explore the findings. A number of topics were selected. This process was repeated until the appropriate number of topics was decided upon. While topic modeling involves many decisions and can be as much art as science (Bail, 2018), the purpose of topic modeling in this context was to develop a simple mathematical summary of the dataset which can help further explore trends and patterns in the data.

2a. Project Set Up and Import Interview Data

library(tidyverse)
library(tidytext)
library(SnowballC)
library(topicmodels)
library(stm)
library(ldatuning)
library(knitr)
library(LDAvis)
library(ggplot2)
library(dplyr)

After setting up the project in R, the data will be imported into R.

CIDRE_interviews <- read_csv("data/Independent Analysis April 18 2023.csv", 
     col_types = cols(
                   Interview = col_character(), 
                   Interviewee = col_character(), 
                   Topic = col_character()
                   )
    )

CIDRE_interviews <- CIDRE_interviews %>% 
    mutate(Interview = strsplit(as.character(Interview), "\n\n\n")) %>% 
    unnest(Interview)

CIDRE_interviews
## # A tibble: 333 × 3
##    Interview                                                       Inter…¹ Topic
##    <chr>                                                           <chr>   <chr>
##  1 "Next is Chris and my picture. Let me make it bigger. Okay, th… Chris … <NA> 
##  2 "making sure that she remembered in the photo that they were"   Chris … <NA> 
##  3 "…so this is the German theatre Museum. This one I went to on … Chris … <NA> 
##  4 "Those are very grown up answers."                              Chris … <NA> 
##  5 "We have to be grown up at some point.\n"                       Chris … <NA> 
##  6 "\nThis is my photo of my personal experience. It was taken by… Kaitli… <NA> 
##  7 "for the tape No it's a very it's a very like peaceful setting… Kaitli… <NA> 
##  8 "Yeah, for the tape, it’s a swan, surrounded by its own feces … Kaitli… <NA> 
##  9 "I feel badly that I already bailed on the public school syste… Karen … <NA> 
## 10 "you did so much photographing. Do you have some favorite phot… Karen … <NA> 
## # … with 323 more rows, and abbreviated variable name ¹​Interviewee

2b. Cast a Document Term Matrix

The text was preprocessed, including converting the data into a tidy text format. This included data tokenization and removal of stop words.

First, the text was tokenized and stop words were removed. Additional stop words were added such as: like, just, well, yeah, lot, stuff, gonna

interviews_tidy <- CIDRE_interviews %>% 
  unnest_tokens(output = word, input = Interview) %>%
  anti_join(stop_words, by = "word") %>%
  filter(!word == "lot"& !word == "stuff"& !word == "gonna"& !word == "like"& !word == "just"& !word == "well"& !word == "yeah") 



interviews_tidy
## # A tibble: 8,136 × 3
##    Interviewee  Topic word   
##    <chr>        <chr> <chr>  
##  1 Chris Alston <NA>  chris  
##  2 Chris Alston <NA>  picture
##  3 Chris Alston <NA>  bigger 
##  4 Chris Alston <NA>  picture
##  5 Chris Alston <NA>  image  
##  6 Chris Alston <NA>  modern 
##  7 Chris Alston <NA>  art    
##  8 Chris Alston <NA>  museum 
##  9 Chris Alston <NA>  floor  
## 10 Chris Alston <NA>  chairs 
## # … with 8,126 more rows

A word count to determine the most common words in the interviews was conducted. These word counts would be later used for creating a document term matrix for topic modeling.

interviews_tidy %>%
  count(word, sort = TRUE)
## # A tibble: 2,759 × 2
##    word           n
##    <chr>      <int>
##  1 people       117
##  2 feel          68
##  3 time          68
##  4 experience    65
##  5 cool          45
##  6 world         45
##  7 kids          43
##  8 germany       42
##  9 picture       41
## 10 students      39
## # … with 2,749 more rows

The terms “people,” “feel,” “time,” and “experience” emerged as most common, reflecting that the study topic was an international learning experience. The terms “community,” “connections” and “professional” are worth attention as well. The terms “white” with 14 instances and “black,” with 13 instances suggests the potential to to explore a potential theme of race.

Creating a Document Term Matrix

Each interview group was treated as a unique document, with a total of ten documents with 2759 terms. Using the existing word counts, a matrix was created that contained a column for each word in the corpus and a value of n for how many times that word occurs in each post.

To create this document term matrix from the interview counts, the cast_dtm() function was used and assigned to the variable interviews_dtm.

interviews_dtm <- interviews_tidy %>%
  count(Topic, word) %>%
  cast_dtm(Topic, word, n)
## [1] "DocumentTermMatrix"    "simple_triplet_matrix"
## <<DocumentTermMatrix (documents: 10, terms: 2759)>>
## Non-/sparse entries: 3128/24462
## Sparsity           : 89%
## Maximal term length: 17
## Weighting          : term frequency (tf)

2c. Preprocessing and (not) Stemming

Next the original data set for structural topic modeling was prepared using the textProcessor() function to remove punctuation elements and stop words to simplify results.

temp <- textProcessor(CIDRE_interviews$Interview, 
                    metadata = CIDRE_interviews,  
                    lowercase=TRUE, 
                    removestopwords=TRUE, 
                    removenumbers=TRUE,  
                    removepunctuation=TRUE, 
                    wordLengths=c(3,Inf),
                    stem=TRUE,
                    onlycharacter= FALSE, 
                    striphtml=TRUE, 
                    customstopwords=NULL)
## Building corpus... 
## Converting to Lower Case... 
## Removing punctuation... 
## Removing stopwords... 
## Removing numbers... 
## Stemming... 
## Creating Output...

Stemming was considered as a preprocessing step to reduce the size of the vocabulary in natural language and thus simplify the model. Stemming reduced the number of terms from 2920 to 2241. This reduction in corpus size of 679 terms does not justify the risk of losing subtleties in meaning between words with similar word stems, such as “support” and “supported” that would be relevant to the findings of the study. Therefore, this project does not use stemming.

meta <- temp$meta
vocab <- temp$vocab
docs <- temp$documents

3. MODEL

The text was modeled to create a mathematical summary of the dataset. The resulting summaries can help trends and patterns in the data to surface, particularly when compared to thematic analysis. Topic Modeling is an unsupervised learning approach that can provide insight into the structure of the dataset.

Three steps were undertaken:

  1. Fitting a Topic Modeling with LDA. The topicmodels package and associated LDA() function for unsupervised classification of the interview data was used to find natural groupings of words, or topics.
  2. Fitting a Structural Topic Model. The stm package and stm() function were used to fit our model and used metadata about documents to improve the assignment of words to “topics” in the corpus.
  3. Choosing K. Finally, an appropriate number of topics was selected.

3a. Fitting a Topic Modeling with LDA

The LDA function or Latent Dirichlet allocation was used because every document contains a mixture of topics and every topic contains a mixture of words. This means that a focus group interview could have an estimated topic proportion of 80% for Topic 1 but also be partly about topic 2. Likewise, words can be shared between topics and words germane to the topic such as “community” and “language” might appear in an individual topic equally.

LDA requires a k value to be specified for the number of topics in the focus group interviews. K was selected as 20 as a starting point. K was then run as 15 by way of comparison.

interviews_lda <- LDA(interviews_dtm, 
                  k = 20,
                  control = list(seed = 588)
                  )

interviews_lda
## A LDA_VEM topic model with 20 topics.
ap_topics <- tidy(interviews_lda, matrix = "beta")
ap_top_terms <- ap_topics %>%
  group_by(topic) %>%
  slice_max(beta, n = 6) %>% 
  ungroup() %>%
  arrange(topic, -beta)

ap_top_terms %>%
  mutate(term = reorder_within(term, beta, topic)) %>%
  ggplot(aes(beta, term, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales = "free") +
  scale_y_reordered()

LDA employs the Term Frequency-Inverse Document Frequency (TF-IDF) metric to assign probabilities.

3b. Fitting a Structural Topic Model

Bail (2018) argues that one reason STM has rising in popularity and use is that it employs meta data about documents to improve the assignment of words to topics in a corpus and that can be used to examine relationships between covariates and documents. This was useful for this project in confirming that topics related to themes revealed in qualtitative data.

The stm Package

Before fitting an STM model, it was necessary to extract the following elements:

docs <- temp$documents 
meta <- temp$meta 
vocab <- temp$vocab 

These elements were then used to fit the model using the same topics for K that were specified for the LDA topic model.

interviews_stm <- stm(documents=docs, 
         data=meta,
         vocab=vocab, 
         K=20,
         max.em.its=25,
         verbose = FALSE)

interviews_stm
## A topic model with 20 topics, 308 documents and a 2329 word dictionary.

The function allows for viewing the most probable words assigned to each topic.

plot.STM(interviews_stm, n = 5)

plot(interviews_stm, n = 5)

3c. Finding K

As alluded to earlier, selecting the number of topics for your model is a non-trivial decision and can dramatically impact your results. Bail (2018) notes that

The results of topic models should not be over-interpreted unless the researcher has strong theoretical apriori about the number of topics in a given corpus, or if the researcher has carefully validated the results of a topic model using both the quantitative and qualitative techniques described above.

The FindTopicsNumber Function

The ldatuning package was used to assist with finding K value.

k_metrics <- FindTopicsNumber(
  interviews_dtm,
  topics = seq(10, 75, by = 5),
  metrics = "Griffiths2004",
  method = "Gibbs",
  control = list(),
  mc.cores = NA,
  return_models = FALSE,
  verbose = FALSE,
  libpath = NULL
)

FindTopicsNumber_plot(k_metrics)

Note that the FindTopicNumbers() function contains three additional metrics for calculating metrics that can be used to estimate the most preferable number of topics for LDA model. We used the Griffiths2004 metrics included in the default example and I’ve also found this to produce the most interpretable results as show in the figure below:

As a general rule of thumb and overly simplistic heuristic, we’re looking for an inflection point in our plot which indicates an optimal number of topics to select for a value of K.

The LDAvis Explorer

The LDAvis explorere was used to expore topic and word distributions.

toLDAvis(mod = interviews_stm, docs = docs)
## Loading required namespace: servr

4. EXPLORE & MODEL

Silge and Robinson (2018) note that fitting at topic model is the “easy part.” The hard part is making sense of the model results and that the rest of the analysis involves exploring and interpreting the model using a variety of approaches which we’ll walkthrough in in this section.

Bail (2018) cautions, however, that:

…post-hoc interpretation of topic models is rather dangerous… and can quickly come to resemble the process of “reading tea leaves,” or finding meaning in patterns that are in fact quite arbitrary or even random.

4a. Exploring Beta Values

The 5 most likely terms assigned to each topic were explored. These per-topic-per-word probabilities, or β (“beta”) values provide the probability of a term (word) belonging to a topic.

terms(interviews_lda, 5)
##      Topic 1      Topic 2       Topic 3       Topic 4         Topic 5      
## [1,] "people"     "world"       "wearing"     "happened"      "connections"
## [2,] "time"       "lesson"      "people"      "culture"       "teachers"   
## [3,] "students"   "garden"      "traditional" "world"         "traditions" 
## [4,] "experience" "sustainable" "clothing"    "understanding" "teaching"   
## [5,] "world"      "plan"        "lederhosen"  "learned"       "program"    
##      Topic 6   Topic 7   Topic 8      Topic 9      Topic 10     Topic 11    
## [1,] "people"  "people"  "time"       "people"     "experience" "people"    
## [2,] "time"    "time"    "experience" "feel"       "people"     "experience"
## [3,] "picture" "world"   "people"     "experience" "time"       "kids"      
## [4,] "germany" "picture" "cool"       "kids"       "cool"       "pictures"  
## [5,] "kids"    "guess"   "read"       "cool"       "germany"    "feel"      
##      Topic 12     Topic 13   Topic 14        Topic 15       Topic 16    
## [1,] "feel"       "cool"     "similar"       "cream"        "time"      
## [2,] "people"     "world"    "love"          "picture"      "experience"
## [3,] "experience" "favorite" "opportunities" "ice"          "kids"      
## [4,] "german"     "padlet"   "combination"   "professional" "picture"   
## [5,] "museum"     "war"      "learner"       "museum"       "thinking"  
##      Topic 17   Topic 18     Topic 19  Topic 20  
## [1,] "people"   "people"     "people"  "time"    
## [2,] "time"     "experience" "germany" "feel"    
## [3,] "thinking" "picture"    "guess"   "cool"    
## [4,] "trip"     "kids"       "talking" "students"
## [5,] "pictures" "world"      "kids"    "pictures"

Topic 10 (experience, time, people, cool, Germany) seems to be about participants experience in Germany.This correlates with the kind of data found in qualitative research on the same data.

tidy_lda <- tidy(interviews_lda)

tidy_lda
## # A tibble: 55,180 × 3
##    topic term         beta
##    <int> <chr>       <dbl>
##  1     1 american 1.15e- 3
##  2     2 american 6.21e-42
##  3     3 american 4.83e-42
##  4     4 american 2.54e-37
##  5     5 american 8.77e- 3
##  6     6 american 7.09e- 4
##  7     7 american 9.35e- 5
##  8     8 american 2.40e- 4
##  9     9 american 2.08e- 3
## 10    10 american 1.10e- 3
## # … with 55,170 more rows
top_terms <- tidy_lda %>%
  group_by(topic) %>%
  slice_max(beta, n = 5, with_ties = FALSE) %>%
  ungroup() %>%
  arrange(topic, -beta)

top_terms %>%
  mutate(term = reorder_within(term, beta, topic)) %>%
  group_by(topic, term) %>%    
  arrange(desc(beta)) %>%  
  ungroup() %>%
  ggplot(aes(beta, term, fill = as.factor(topic))) +
  geom_col(show.legend = FALSE) +
  scale_y_reordered() +
  labs(title = "Top 5 terms in each LDA topic",
       x = expression(beta), y = NULL) +
  facet_wrap(~ topic, ncol = 4, scales = "free")

5. COMMUNICATE

As Silge and Robinson note (2018), fitting the topic model is easy relative to the more challenging work of interpreting the model results.

Comparing results of thematic analysis conducted by researchers to topic modeling conducted in R can provide insights into the limitations and benefits of both forms of qualitative research. As Bail (2018) warns, “…post-hoc interpretation of topic models is rather dangerous… and can quickly come to resemble the process of ‘reading tea leaves,’ or finding meaning in patterns that are in fact quite arbitrary or even random.”

The same description could be applied to thematic analysis, a process which is creative, time consuming, and can reflect the biases of the researchers. By comparing the results of both approaches, researchers and practitioners can gain a deeper understanding of the data and the context in which it was collected. This can lead to transformative insights into how qualitative research can be conducted in a more rigorous and systematic manner, while still allowing for the creativity and subjectivity that are inherent in this type of research. Moreover, reflecting on the limitations and benefits of both thematic analysis and topic modeling can help researchers and practitioners to identify areas for improvement in their own research practices, as well as provide guidance for future research studies. Ultimately, this can lead to more robust and meaningful qualitative research that contributes to the advancement of knowledge in a range of fields.

Initial findings from thematic analysis of focus group data indicated that

1.) Self-selected digital projects allowed participants to develop professional knowledge related to their specific teaching content, curriculum, and classroom;

2.) International immersive experience with targeted professional development provided an opportunity for reflections on pandemic/post-pandemic instruction; and

3.) Teachers reflected that the experience had an impact on their teaching dispositions and plans for the future.

Comparing topics to intitial findings from thematic analysis suggest that topic analysis reflects general, superficial interperetations of the expeirence. Words such as “cool” “experience” “people” “feel” reflect a postive, but superficial experience in Germany. Thematic analysis, conducted by researchers with personal relationships with participants suggests a nuanced, more sophisticated reading of the data. This anaylsis reflects outcomes from the experience with suggest deep change in teacher values and practices which do not seem to be suggested from topic modeling. While the text minign approach allows for analysis of a large corpus of data, qualitative reseearch from a team offers a more in-depth analysis. The two have value together in that topic modeling can be used with a larger corpus of data and can offer a confirmation of the general direction of themes created in thematic analysis. The use of topic modeling in addition to thematic analysis can provide a form of triangulation valuable to the credibility of a qualitative research study.

Experience examining which words tend to follow others immediately, or that tend to co-occur within the same documents.

Comparing results of thematic analysis conducted by researchers to topic modeling conducted in R can provide insights into the limitations and benefits of both forms of qualitative research. As Bail (2018) warns, “…post-hoc interpretation of topic models is rather dangerous… and can quickly come to resemble the process of ‘reading tea leaves,’ or finding meaning in patterns that are in fact quite arbitrary or even random.” The same description could be applied to thematic analysis, a process which is creative, time consuming, and can reflect the biases of the researchers. By comparing the results of both approaches, researchers and practitioners can gain a deeper understanding of the data and the context in which it was collected. This can lead to transformative insights into how qualitative research can be conducted in a more rigorous and systematic manner, while still allowing for the creativity and subjectivity that are inherent in this type of research. Moreover, reflecting on the limitations and benefits of both thematic analysis and topic modeling can help researchers and practitioners to identify areas for improvement in their own research practices, as well as provide guidance for future research studies. Ultimately, this can lead to more robust and meaningful qualitative research that contributes to the advancement of knowledge in a range of fields.

References

Braun, V., & Clarke, V. (2022). Conceptual and design thinking for thematic analysis. Qualitative Psychology, 9(1), 3–26. https://doi.org/10.1037/qup0000196

Bail, C. (2018). Strengths and weaknesses of text as data. Retrieved from https://sicss.io/2019/materials/day3-text-analysis/topic-modeling/rmarkdown/Topic_Modeling.html

Gillies, M., Murthy, D., Brenton, H., & Olaniyan, R. (2022). Theme and topic: How qualitative research and topic modeling can be brought together. arXiv preprint arXiv:2210.00707. https://doi.org/10.48550/arXiv.2210.00707

Silge, J., & Robinson, D. (2017). Text mining with R: A tidy approach. O’Reilly Media, Inc. Retrieved from: https://www.tidytextmining.com/topicmodeling.html

Wickham, H. & Grolemund, G. (2017). R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. O’Reilly Media, Inc. Retrieved from https://r4ds.had.co.nz/


LS0tCnRpdGxlOiAiVXNpbmcgUiB0byBBbmFseXplIFF1YWxpdGF0aXZlIERhdGEgZnJvbSBUZWFjaGVyc+KAmSBJbnRlcm5hdGlvbmFsIFByb2Zlc3Npb25hbCBEZXZlbG9wbWVudCBFeHBlcmllbmNlIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogVFJVRQplZGl0b3Jfb3B0aW9uczogCiAgbWFya2Rvd246IAogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIyBBYnN0cmFjdAoKVGhpcyBwcm9qZWN0IHJlcG9ydHMgYSBtZXRob2RvbG9naWNhbCBhZHZhbmNlbWVudCBvbiBob3cgdG9waWMgbW9kZWxpbmcKY2FuIGJlIHVzZWQgdG8gYW5hbHl6ZSBxdWFsaXRhdGl2ZSBkYXRhIGZyb20gdHJhbnNjcmlwdHMgb2YgZm9jdXMgZ3JvdXBzCmNvbmR1Y3RlZCB3aXRoIHBhcnRpY2lwYW50cyBpbiBhbiBpbnRlcm5hdGlvbmFsIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudApwcm9ncmFtLiBUaGUgcHJvZ3JhbSBpcyBkZXNpZ25lZCB0byBwcmVwYXJlIGluc2VydmljZSBlZHVjYXRvcnMgZm9yIGN1bHR1cmFsbHktcmVzcG9uc2l2ZQp0ZWFjaGluZyAoQ1JUKSB0aHJvdWdoIHByYWN0aWNlIHdpdGggdGhlIGRldmVsb3BtZW50IG9mIHRlY2huaWNhbApyZXByZXNlbnRhdGlvbnMgb2YgY3VsdHVyYWwgdGhlbWVzIGluIGFuIGludGVybmF0aW9uYWwgY29udGV4dC4gVGhlbWVzCmRldmVsb3BlZCB1c2luZyB0b3BpYyBtb2RlbGluZyBjYW4gYmUgY29tcGFyZWQgdG8gZXhpc3RpbmcgdGhlbWF0aWMKYW5hbHlzaXMgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIG9uIHRoZSBzYW1lIGRhdGEuIFRoaXMgd2lsbCBwcm92aWRlCmluc2lnaHQgaW50byB0aGUgc3RyZW5ndGhzIGFuZCB3ZWFrbmVzc2VzIG9mIGVhY2ggYXBwcm9hY2ggYW5kCmRlbW9uc3RyYXRlIHRoZSBwb3RlbnRpYWwgb2YgdG9waWMgbW9kZWxpbmcgdG8gZW5oYW5jZSBxdWFsaXRhdGl2ZSBkYXRhCmFuYWx5c2lzLiBUaGlzIHdpbGwgYmUgdXNlZnVsIGZvciBmdXR1cmUgcmVzZWFyY2hlcnMgaW50ZXJlc3RlZCBpbiB0aGUKaW50ZXJhY3Rpb24gYmV0d2VlbiBxdWFsaXRhdGl2ZSBtZXRob2RvbG9neSBhbmQgdG9waWMgbW9kZWxpbmcuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIDEuIFBSRVBBUkUKCiMjIyAxYS4gKipEYXRhIHNvdXJjZXMgdXNlZCBmb3IgdGV4dCBhbmFseXNpcyoqCgoqKkNvbnRleHQ6IFByb2Zlc3Npb25hbCBEZXZlbG9wbWVudCBBYnJvYWQqKgoKVGhlIGRhdGEgYXJlIGZyb20gYW4gb25nb2luZywgaW50ZXJuYXRpb25hbCwgcHJvZmVzc2lvbmFsIGRldmVsb3BtZW50CnByb2dyYW0gZm9yIGluc2VydmljZSB0ZWFjaGVycy4gSXQgaW5jbHVkZXMgdGhyZWUgU2F0dXJkYXkgY2xhc3NlcyBpbgp0aGUgc3ByaW5nLCB0d28gd2Vla3Mgb2YgYSBzdHVkeSBhYnJvYWQgcHJvZ3JhbSBpbiB0aGUgc3VtbWVyIHRvIGFuCmludGVybmF0aW9uYWwgZGVzdGluYXRpb24gKGluIDIwMjIsIHRvIE11bmljaCBHZXJtYW55KSBhbmQgb25lIGZvbGxvdyB1cApzZXNzaW9uIGluIHRoZSBmYWxsLiBJbiB0aGlzIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudCBhYnJvYWQsIHRlYWNoZXJzCmJ1aWxkIGEgcG9ydGZvbGlvIHRoYXQgcmVwcmVzZW50cyBhIGNob3NlbiBjdWx0dXJhbCB0aGVtZSwgaW5jbHVkaW5nIGEKbGVzc29uIHBsYW4gaWxsdXN0cmF0aW5nIGhvdyB0aGV5IHBsYW4gdG8gYXBwbHkgdGVjaG5pY2FsIGN1bHR1cmFsCnJlcHJlc2VudGF0aW9uIGFuZC9vciBhbmFseXNpcyBpbiB0aGVpciBvd24gY2xhc3Nyb29tcy4gVGhlIHByb2dyYW0gYWltcwp0byBwcm92aWRlIHRlYWNoZXJzIHdpdGggZXhwZXJpZW5jZXMgcHJhY3RpY2luZyB3aXRoIGN1bHR1cmFsIGZyYW1lcyBhbmQKcmVwcmVzZW50YXRpb25hbCB0b29scywgc28gdGhleSBjYW4gd29yayB3aXRoIHRoZWlyIG93biBzdHVkZW50cyB0bwplbGljaXQgYW5kIHJlcHJlc2VudCBkaXZlcnNlIGN1bHR1cmFsIGlkZW50aXRpZXMgYW5kIHBlcnNwZWN0aXZlcy4KCioqRGF0YSBDb2xsZWN0aW9uIGFuZCBBbmFseXNpcyoqCgpGaXJzdCwgdXNpbmcgcXVhbGl0YXRpdmUgbWV0aG9kcywgdGhlIHJlc2VhcmNoIHRlYW0gYW5hbHl6ZWQgZGF0YQpjb2xsZWN0ZWQgZHVyaW5nIGZvY3VzIGdyb3VwcywgZnJvbSBkaWdpdGFsIHBvcnRmb2xpb3MsIGFuZCBmcm9tCm9ic2VydmF0aW9ucyBkdXJpbmcgdGhlIHByb2Zlc3Npb25hbCBkZXZlbG9wbWVudCBwcm9ncmFtLiBEYXRhIGNvbGxlY3RlZApjb25zaXN0ZWQgb2YgcmVzZWFyY2hlciBtZW1vcywgcHJvamVjdHMgYW5kIGFydGlmYWN0cyBjcmVhdGVkIGJ5IDE5CnRlYWNoZXJzLCBhbmQgcG9zdC1yZWZsZWN0aXZlIGZvY3VzIGdyb3VwcyBhZnRlciB0aGUgcHJvZmVzc2lvbmFsCmRldmVsb3BtZW50IGV4cGVyaWVuY2UuIFVzaW5nIHRoZSB0cmFuc2NyaXB0cyBmcm9tIHRoZSBmb2N1cyBncm91cHMsCnBhcnRpY2lwYW50cycgcG9ydGZvbGlvcywgYW5kIHJlc2VhcmNoZXIgb2JzZXJ2YXRpb25zLCBCcmF1biBhbmQKQ2xhcmtlJ3MgKDIwMjIpIHByb2Nlc3Mgb2YgcmVmbGV4aXZlIHRoZW1hdGljIGFuYWx5c2lzIHRvIGFuYWx5emUgZm9jdXMKZ3JvdXAgZGF0YSB3YXMgdXNlZC7CoAoKSW5pdGlhbCBmaW5kaW5ncyBmcm9tIHRoZW1hdGljIGFuYWx5c2lzIG9mIGZvY3VzIGdyb3VwIGRhdGEgaW5kaWNhdGVkCnRoYXQKCjEuKSBTZWxmLXNlbGVjdGVkIGRpZ2l0YWwgcHJvamVjdHMgYWxsb3dlZCBwYXJ0aWNpcGFudHMgdG8gZGV2ZWxvcAoqKnByb2Zlc3Npb25hbCBrbm93bGVkZ2UqKiByZWxhdGVkIHRvIHRoZWlyIHNwZWNpZmljIHRlYWNoaW5nIGNvbnRlbnQsCmN1cnJpY3VsdW0sIGFuZCBjbGFzc3Jvb207CgoyLikgSW50ZXJuYXRpb25hbCBpbW1lcnNpdmUgZXhwZXJpZW5jZSB3aXRoIHRhcmdldGVkIHByb2Zlc3Npb25hbApkZXZlbG9wbWVudCBwcm92aWRlZCBhbiBvcHBvcnR1bml0eSBmb3IgKipyZWZsZWN0aW9ucyBvbgpwYW5kZW1pYy9wb3N0LXBhbmRlbWljIGluc3RydWN0aW9uKio7IGFuZAoKMy4pIFRlYWNoZXJzIHJlZmxlY3RlZCB0aGF0IHRoZSBleHBlcmllbmNlIGhhZCBhbiBpbXBhY3Qgb24gdGhlaXIKKip0ZWFjaGluZyBkaXNwb3NpdGlvbnMgYW5kIHBsYW5zIGZvciB0aGUgZnV0dXJlLioqCgpUaGlzIHByb2plY3Qgd2lsbCBvdXRsaW5lIGEgc2Vjb25kIHN0ZXAgaW4gdGhpcyBwcm9jZXNzLCBpbiB3aGljaCB0aGUKc2FtZSBkYXRhIHdpbGwgYmUgYW5hbHl6ZWQgdXNpbmcgdG9waWMgbW9kZWxpbmcuIFRvcGljIG1vZGVsaW5nIGlzIGEKbWFjaGluZSBsZWFybmluZyB0ZWNobmlxdWUgdGhhdCBhdXRvbWF0aWNhbGx5IGFuYWx5emVzIHRleHQgZGF0YSB0bwpkZXRlcm1pbmUgY2x1c3RlciB3b3JkcyBmb3IgYSBzZXQgb2YgZG9jdW1lbnRzLiBUaGlzIGlzIGtub3duIGFzCid1bnN1cGVydmlzZWQnIG1hY2hpbmUgbGVhcm5pbmcgYmVjYXVzZSBpdCBkb2Vzbid0IHJlcXVpcmUgYSBwcmVkZWZpbmVkCmxpc3Qgb2YgdGFncyBvciB0cmFpbmluZyBkYXRhIHRoYXQncyBiZWVuIHByZXZpb3VzbHkgY2xhc3NpZmllZCBieQpodW1hbnMuIFRoaXMgYWRkaXRpb25hbCBzdGVwIGluIGFuYWx5emluZyB0aGUgZGF0YSBhZHZhbmNlcyB0aGUgZmllbGQgb2YKcXVhbGl0YXRpdmUgcmVzZWFyY2ggYXMgaXQgb2ZmZXJzIGEgbWVhbnMgb2YgcmVmbGVjdGluZyBvbiB0aGUKY29tcGFyaXNvbiBvZiB0aGUgdHdvIHNldHMgb2YgcmVzdWx0cy4KCiMjIyAxYi4gR3VpZGluZyBRdWVzdGlvbgoKV2l0aCB0aGUgaW5jcmVhc2luZyBhbW91bnQgb2YgcXVhbGl0YXRpdmUgZGF0YSBiZWluZyBnZW5lcmF0ZWQgaW4KcmVzZWFyY2ggc3R1ZGllcywgaXQgaXMgZXNzZW50aWFsIHRvIGhhdmUgZWZmZWN0aXZlIG1ldGhvZHMgZm9yCmFuYWx5emluZyBhbmQgaW50ZXJwcmV0aW5nIHRoaXMgaW5mb3JtYXRpb24uIFRoZSB1c2Ugb2YgdG9waWMgbW9kZWxpbmcKaW4gdGhlIGFuYWx5c2lzIG9mIHRleHR1YWwgZGF0YSBoYXMgZ2FpbmVkIHBvcHVsYXJpdHkgaW4gcmVjZW50IHllYXJzCmR1ZSB0byBpdHMgYWJpbGl0eSB0byBpZGVudGlmeSBoaWRkZW4gdGhlbWVzIGFuZCBwYXR0ZXJucyB3aXRoaW4gbGFyZ2UKZGF0YXNldHMuIFRoaXMgcHJvamVjdCBkZXNjcmliZXMgYSBwb3RlbnRpYWwgbWV0aG9kb2xvZ2ljYWwgYWR2YW5jZW1lbnQKb24gaG93IHRvcGljIG1vZGVsaW5nIGNhbiBiZSB1c2VkIHRvIGFuYWx5emUgcXVhbGl0YXRpdmUgZGF0YS4KClRodXMsIHRoZSBwcmltYXJ5IHJlc2VhcmNoIHF1ZXN0aW9uIGlzOgoKKipXaGF0IGRvZXMgdG9waWMgbW9kZWxpbmcgaW4gdGhlIGFuYWx5c2lzIG9mIHRleHR1YWwgZGF0YSBmcm9tIGZvY3VzCmdyb3VwcyB3aXRoIGluc2VydmljZSB0ZWFjaGVycyBwYXJ0aWNpcGF0aW5nIGluIGludGVybmF0aW9uYWwKcHJvZmVzc2lvbmFsIGRldmVsb3BtZW50IHJldmVhbCBhYm91dCBob3cgdG9waWMgbW9kZWxpbmcgY2FuIGVuaGFuY2UKcXVhbGl0YXRpdmUgcmVzZWFyY2ggZGF0YT8qKgoKIyMgMi4gV1JBTkdMRQoKVG8gYW5hbHl6ZSB0aGUgdGV4dHVhbCBkYXRhIHVzaW5nIHRvcGljIG1vZGVsaW5nLCB0aGUgd29ya2Zsb3cgb2YgdGhlCnByb2Nlc3Mgd2lsbCBpbmNsdWRlIGRhdGEgd3JhbmdsaW5nLCBtb2RlbGluZywgYW5kIGV4cGxvcmF0aW9uIGFzCmZvbGxvd3M6wqAKClRoZSBkYXRhIHdpbGwgYmUgd3JhbmdsZWQsIGEgcHJvY2VzcyB3aGljaCBpbnZvbHZlcyBzb21lIGNvbWJpbmF0aW9uIG9mCmNsZWFuaW5nLCByZXNoYXBpbmcsIHRyYW5zZm9ybWluZywgYW5kIG1lcmdpbmcgZGF0YSAoV2lja2hhbSAmCkdyb2xlbXVuZCwgMjAxNykuIFRoZSB0ZXh0IHdpbGwgYmUgcHJlcHJvY2Vzc2VkLCBpbmNsdWRpbmcgY29udmVydGluZwp0aGUgZGF0YSBpbnRvIGEgdGlkeSB0ZXh0IGZvcm1hdC4gVGhpcyBpbmNsdWRlcyBkYXRhIHRva2VuaXphdGlvbiwKcmVtb3ZhbCBvZiBzdG9wIHdvcmRzLCBhbmQgc3RlbW1pbmcuCgpUaGUgdGV4dCB3aWxsIHRoZW4gYmUgYW5hbHl6ZWQgYnkgZml0dGluZyBhIHRvcGljIG1vZGVsaW5nIGFsZ29yaXRobQp1c2luZyBMYXRlbnQgRGlyaWNobGV0IEFsbG9jYXRpb24gKExEQSkuIFRoZW4gYmV0YSB2YWx1ZXMgd2VyZSBjcmVhdGVkIHRvCmV4cGxvcmUgdGhlIGZpbmRpbmdzLiBBIG51bWJlciBvZiB0b3BpY3Mgd2VyZSBzZWxlY3RlZC4gVGhpcyBwcm9jZXNzIHdhcyByZXBlYXRlZAp1bnRpbCB0aGUgYXBwcm9wcmlhdGUgbnVtYmVyIG9mIHRvcGljcyB3YXMgZGVjaWRlZCB1cG9uLiBXaGlsZSB0b3BpYwptb2RlbGluZyBpbnZvbHZlcyBtYW55IGRlY2lzaW9ucyBhbmQgY2FuIGJlIGFzIG11Y2ggYXJ0IGFzIHNjaWVuY2UKKEJhaWwsIDIwMTgpLCB0aGUgcHVycG9zZSBvZiB0b3BpYyBtb2RlbGluZyBpbiB0aGlzIGNvbnRleHQgd2FzIHRvCmRldmVsb3AgYSBzaW1wbGUgbWF0aGVtYXRpY2FsIHN1bW1hcnkgb2YgdGhlIGRhdGFzZXQgd2hpY2ggY2FuIGhlbHAgZnVydGhlciBleHBsb3JlIHRyZW5kcyBhbmQgcGF0dGVybnMgaW4gdGhlIGRhdGEuCgojIyMgMmEuIFByb2plY3QgU2V0IFVwIGFuZCBJbXBvcnQgSW50ZXJ2aWV3IERhdGEKCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KFNub3diYWxsQykKbGlicmFyeSh0b3BpY21vZGVscykKbGlicmFyeShzdG0pCmxpYnJhcnkobGRhdHVuaW5nKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KExEQXZpcykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpgYGAKCkFmdGVyIHNldHRpbmcgdXAgdGhlIHByb2plY3QgaW4gUiwgdGhlIGRhdGEgd2lsbCBiZSBpbXBvcnRlZCBpbnRvIFIuCgpgYGB7ciByZWFkLWNzdn0KQ0lEUkVfaW50ZXJ2aWV3cyA8LSByZWFkX2NzdigiZGF0YS9JbmRlcGVuZGVudCBBbmFseXNpcyBBcHJpbCAxOCAyMDIzLmNzdiIsIAogICAgIGNvbF90eXBlcyA9IGNvbHMoCiAgICAgICAgICAgICAgICAgICBJbnRlcnZpZXcgPSBjb2xfY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgSW50ZXJ2aWV3ZWUgPSBjb2xfY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgVG9waWMgPSBjb2xfY2hhcmFjdGVyKCkKICAgICAgICAgICAgICAgICAgICkKICAgICkKCkNJRFJFX2ludGVydmlld3MgPC0gQ0lEUkVfaW50ZXJ2aWV3cyAlPiUgCiAgICBtdXRhdGUoSW50ZXJ2aWV3ID0gc3Ryc3BsaXQoYXMuY2hhcmFjdGVyKEludGVydmlldyksICJcblxuXG4iKSkgJT4lIAogICAgdW5uZXN0KEludGVydmlldykKCkNJRFJFX2ludGVydmlld3MKYGBgCgojIyMgMmIuIENhc3QgYSBEb2N1bWVudCBUZXJtIE1hdHJpeAoKVGhlIHRleHQgd2FzIHByZXByb2Nlc3NlZCwgaW5jbHVkaW5nIGNvbnZlcnRpbmcgdGhlIGRhdGEgaW50byBhIHRpZHkKdGV4dCBmb3JtYXQuIFRoaXMgaW5jbHVkZWQgZGF0YSB0b2tlbml6YXRpb24gYW5kIHJlbW92YWwgb2Ygc3RvcCB3b3Jkcy4KCkZpcnN0LCB0aGUgdGV4dCB3YXMgdG9rZW5pemVkIGFuZCBzdG9wIHdvcmRzIHdlcmUgcmVtb3ZlZC4gQWRkaXRpb25hbApzdG9wIHdvcmRzIHdlcmUgYWRkZWQgc3VjaCBhczogbGlrZSwganVzdCwgd2VsbCwgeWVhaCwgbG90LCBzdHVmZiwgZ29ubmEKCmBgYHtyIHRva2VuaXplLWludGVydmlld3N9CmludGVydmlld3NfdGlkeSA8LSBDSURSRV9pbnRlcnZpZXdzICU+JSAKICB1bm5lc3RfdG9rZW5zKG91dHB1dCA9IHdvcmQsIGlucHV0ID0gSW50ZXJ2aWV3KSAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcywgYnkgPSAid29yZCIpICU+JQogIGZpbHRlcighd29yZCA9PSAibG90IiYgIXdvcmQgPT0gInN0dWZmIiYgIXdvcmQgPT0gImdvbm5hIiYgIXdvcmQgPT0gImxpa2UiJiAhd29yZCA9PSAianVzdCImICF3b3JkID09ICJ3ZWxsIiYgIXdvcmQgPT0gInllYWgiKSAKCgoKaW50ZXJ2aWV3c190aWR5CmBgYAoKQSB3b3JkIGNvdW50IHRvIGRldGVybWluZSB0aGUgbW9zdCBjb21tb24gd29yZHMgaW4gdGhlIGludGVydmlld3Mgd2FzCmNvbmR1Y3RlZC4gVGhlc2Ugd29yZCBjb3VudHMgd291bGQgYmUgbGF0ZXIgdXNlZCBmb3IgY3JlYXRpbmcgYSBkb2N1bWVudAp0ZXJtIG1hdHJpeCBmb3IgdG9waWMgbW9kZWxpbmcuCgpgYGB7ciBjb3VudC13b3Jkc30KaW50ZXJ2aWV3c190aWR5ICU+JQogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQpgYGAKClRoZSB0ZXJtcyAicGVvcGxlLCIgImZlZWwsIiAidGltZSwiIGFuZCAiZXhwZXJpZW5jZSIgZW1lcmdlZCBhcyBtb3N0CmNvbW1vbiwgcmVmbGVjdGluZyB0aGF0IHRoZSBzdHVkeSB0b3BpYyB3YXMgYW4gaW50ZXJuYXRpb25hbCBsZWFybmluZwpleHBlcmllbmNlLiBUaGUgdGVybXMgImNvbW11bml0eSwiICJjb25uZWN0aW9ucyIgYW5kICJwcm9mZXNzaW9uYWwiIGFyZQp3b3J0aCBhdHRlbnRpb24gYXMgd2VsbC4gVGhlIHRlcm1zICJ3aGl0ZSIgd2l0aCAxNCBpbnN0YW5jZXMgYW5kCiJibGFjaywiIHdpdGggMTMgaW5zdGFuY2VzIHN1Z2dlc3RzIHRoZSBwb3RlbnRpYWwgdG8gCnRvIGV4cGxvcmUgYSBwb3RlbnRpYWwgdGhlbWUgb2YgcmFjZS4KCgoKIyMjIyBDcmVhdGluZyBhIERvY3VtZW50IFRlcm0gTWF0cml4CgpFYWNoIGludGVydmlldyBncm91cCB3YXMgdHJlYXRlZCBhcyBhIHVuaXF1ZSBkb2N1bWVudCwgd2l0aCBhIHRvdGFsIG9mCnRlbiBkb2N1bWVudHMgd2l0aCAyNzU5IHRlcm1zLiBVc2luZyB0aGUgZXhpc3Rpbmcgd29yZCBjb3VudHMsIGEgbWF0cml4CndhcyBjcmVhdGVkIHRoYXQgY29udGFpbmVkIGEgY29sdW1uIGZvciBlYWNoIHdvcmQgaW4gdGhlIGNvcnB1cyBhbmQgYQp2YWx1ZSBvZiBuIGZvciBob3cgbWFueSB0aW1lcyB0aGF0IHdvcmQgb2NjdXJzIGluIGVhY2ggcG9zdC4KClRvIGNyZWF0ZSB0aGlzIGRvY3VtZW50IHRlcm0gbWF0cml4IGZyb20gdGhlIGludGVydmlldyBjb3VudHMsIHRoZQpjYXN0X2R0bSgpIGZ1bmN0aW9uIHdhcyB1c2VkIGFuZCBhc3NpZ25lZCB0byB0aGUgdmFyaWFibGUKaW50ZXJ2aWV3c19kdG0uCgpgYGB7ciBjYXN0LWR0bX0KaW50ZXJ2aWV3c19kdG0gPC0gaW50ZXJ2aWV3c190aWR5ICU+JQogIGNvdW50KFRvcGljLCB3b3JkKSAlPiUKICBjYXN0X2R0bShUb3BpYywgd29yZCwgbikKYGBgCgpgYGB7ciBjbGFzcy1kdG0sIGVjaG89RkFMU0V9CmNsYXNzKGludGVydmlld3NfZHRtKQoKaW50ZXJ2aWV3c19kdG0KYGBgCgojIyMgMmMuIFByZXByb2Nlc3NpbmcgYW5kIChub3QpIFN0ZW1taW5nCgpOZXh0IHRoZSBvcmlnaW5hbCBkYXRhIHNldCBmb3Igc3RydWN0dXJhbCB0b3BpYyBtb2RlbGluZyB3YXMgcHJlcGFyZWQKdXNpbmcgdGhlIGB0ZXh0UHJvY2Vzc29yKClgIGZ1bmN0aW9uIHRvIHJlbW92ZSBwdW5jdHVhdGlvbiBlbGVtZW50cyBhbmQKc3RvcCB3b3JkcyB0byBzaW1wbGlmeSByZXN1bHRzLgoKYGBge3IgdGV4dFByb2Nlc3Nvcn0KdGVtcCA8LSB0ZXh0UHJvY2Vzc29yKENJRFJFX2ludGVydmlld3MkSW50ZXJ2aWV3LCAKICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IENJRFJFX2ludGVydmlld3MsICAKICAgICAgICAgICAgICAgICAgICBsb3dlcmNhc2U9VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlc3RvcHdvcmRzPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIHJlbW92ZW51bWJlcnM9VFJVRSwgIAogICAgICAgICAgICAgICAgICAgIHJlbW92ZXB1bmN0dWF0aW9uPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIHdvcmRMZW5ndGhzPWMoMyxJbmYpLAogICAgICAgICAgICAgICAgICAgIHN0ZW09VFJVRSwKICAgICAgICAgICAgICAgICAgICBvbmx5Y2hhcmFjdGVyPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgc3RyaXBodG1sPVRSVUUsIAogICAgICAgICAgICAgICAgICAgIGN1c3RvbXN0b3B3b3Jkcz1OVUxMKQpgYGAKClN0ZW1taW5nIHdhcyBjb25zaWRlcmVkIGFzIGEgcHJlcHJvY2Vzc2luZyBzdGVwIHRvIHJlZHVjZSB0aGUgc2l6ZSBvZgp0aGUgdm9jYWJ1bGFyeSBpbiBuYXR1cmFsIGxhbmd1YWdlIGFuZCB0aHVzIHNpbXBsaWZ5IHRoZSBtb2RlbC4gU3RlbW1pbmcKcmVkdWNlZCB0aGUgbnVtYmVyIG9mIHRlcm1zIGZyb20gMjkyMCB0byAyMjQxLiBUaGlzIHJlZHVjdGlvbiBpbiBjb3JwdXMKc2l6ZSBvZiA2NzkgdGVybXMgZG9lcyBub3QganVzdGlmeSB0aGUgcmlzayBvZiBsb3Npbmcgc3VidGxldGllcyBpbgptZWFuaW5nIGJldHdlZW4gd29yZHMgd2l0aCBzaW1pbGFyIHdvcmQgc3RlbXMsIHN1Y2ggYXMgInN1cHBvcnQiIGFuZAoic3VwcG9ydGVkIiB0aGF0IHdvdWxkIGJlIHJlbGV2YW50IHRvIHRoZSBmaW5kaW5ncyBvZiB0aGUgc3R1ZHkuClRoZXJlZm9yZSwgdGhpcyBwcm9qZWN0IGRvZXMgbm90IHVzZSBzdGVtbWluZy4KCmBgYHtyIHN0bS1pbnB1dHN9Cm1ldGEgPC0gdGVtcCRtZXRhCnZvY2FiIDwtIHRlbXAkdm9jYWIKZG9jcyA8LSB0ZW1wJGRvY3VtZW50cwpgYGAKCiMjIDMuIE1PREVMCgpUaGUgdGV4dCB3YXMgbW9kZWxlZCB0byBjcmVhdGUgYSBtYXRoZW1hdGljYWwgc3VtbWFyeSBvZiB0aGUgZGF0YXNldC4KVGhlIHJlc3VsdGluZyBzdW1tYXJpZXMgY2FuIGhlbHAgdHJlbmRzIGFuZCBwYXR0ZXJucyBpbiB0aGUgZGF0YSB0bwpzdXJmYWNlLCBwYXJ0aWN1bGFybHkgd2hlbiBjb21wYXJlZCB0byB0aGVtYXRpYyBhbmFseXNpcy4gVG9waWMgTW9kZWxpbmcKaXMgYW4gdW5zdXBlcnZpc2VkIGxlYXJuaW5nIGFwcHJvYWNoIHRoYXQgY2FuIHByb3ZpZGUgaW5zaWdodCBpbnRvIHRoZQpzdHJ1Y3R1cmUgb2YgdGhlIGRhdGFzZXQuCgpUaHJlZSBzdGVwcyB3ZXJlIHVuZGVydGFrZW46CgphLiAgKipGaXR0aW5nIGEgVG9waWMgTW9kZWxpbmcgd2l0aCBMREEqKi4gVGhlIGB0b3BpY21vZGVsc2AgcGFja2FnZSBhbmQKICAgIGFzc29jaWF0ZWQgYExEQSgpYCBmdW5jdGlvbiBmb3IgdW5zdXBlcnZpc2VkIGNsYXNzaWZpY2F0aW9uIG9mIHRoZQogICAgaW50ZXJ2aWV3IGRhdGEgd2FzIHVzZWQgdG8gZmluZCBuYXR1cmFsIGdyb3VwaW5ncyBvZiB3b3Jkcywgb3IKICAgIHRvcGljcy4KYi4gICoqRml0dGluZyBhIFN0cnVjdHVyYWwgVG9waWMgTW9kZWwqKi4gVGhlIGBzdG1gIHBhY2thZ2UgYW5kIGBzdG0oKWAKICAgIGZ1bmN0aW9uIHdlcmUgdXNlZCB0byBmaXQgb3VyIG1vZGVsIGFuZCB1c2VkIG1ldGFkYXRhIGFib3V0CiAgICBkb2N1bWVudHMgdG8gaW1wcm92ZSB0aGUgYXNzaWdubWVudCBvZiB3b3JkcyB0byAidG9waWNzIiBpbiB0aGUKICAgIGNvcnB1cy4KYy4gICoqQ2hvb3NpbmcgSy4qKiBGaW5hbGx5LCBhbiBhcHByb3ByaWF0ZSBudW1iZXIgb2YgdG9waWNzIHdhcwogICAgc2VsZWN0ZWQuCgojIyMgM2EuIEZpdHRpbmcgYSBUb3BpYyBNb2RlbGluZyB3aXRoIExEQQoKVGhlIExEQSBmdW5jdGlvbiBvciBMYXRlbnQgRGlyaWNobGV0IGFsbG9jYXRpb24gd2FzIHVzZWQgYmVjYXVzZSBldmVyeQpkb2N1bWVudCBjb250YWlucyBhIG1peHR1cmUgb2YgdG9waWNzIGFuZCBldmVyeSB0b3BpYyBjb250YWlucyBhIG1peHR1cmUKb2Ygd29yZHMuIFRoaXMgbWVhbnMgdGhhdCBhIGZvY3VzIGdyb3VwIGludGVydmlldyBjb3VsZCBoYXZlIGFuCmVzdGltYXRlZCB0b3BpYyBwcm9wb3J0aW9uIG9mIDgwJSBmb3IgVG9waWMgMSBidXQgYWxzbyBiZSBwYXJ0bHkgYWJvdXQKdG9waWMgMi4gTGlrZXdpc2UsIHdvcmRzIGNhbiBiZSBzaGFyZWQgYmV0d2VlbiB0b3BpY3MgYW5kIHdvcmRzIGdlcm1hbmUKdG8gdGhlIHRvcGljIHN1Y2ggYXMgImNvbW11bml0eSIgYW5kICJsYW5ndWFnZSIgbWlnaHQgYXBwZWFyIGluIGFuCmluZGl2aWR1YWwgdG9waWMgZXF1YWxseS4KCkxEQSByZXF1aXJlcyBhIGsgdmFsdWUgdG8gYmUgc3BlY2lmaWVkIGZvciB0aGUgbnVtYmVyIG9mIHRvcGljcyBpbiB0aGUKZm9jdXMgZ3JvdXAgaW50ZXJ2aWV3cy4gSyB3YXMgc2VsZWN0ZWQgYXMgMjAgYXMgYSBzdGFydGluZyBwb2ludC4gSyB3YXMKdGhlbiBydW4gYXMgMTUgYnkgd2F5IG9mIGNvbXBhcmlzb24uCgpgYGB7ciBMREF9CgppbnRlcnZpZXdzX2xkYSA8LSBMREEoaW50ZXJ2aWV3c19kdG0sIAogICAgICAgICAgICAgICAgICBrID0gMjAsCiAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHNlZWQgPSA1ODgpCiAgICAgICAgICAgICAgICAgICkKCmludGVydmlld3NfbGRhCmBgYAoKYGBge3J9CmFwX3RvcGljcyA8LSB0aWR5KGludGVydmlld3NfbGRhLCBtYXRyaXggPSAiYmV0YSIpCmFwX3RvcF90ZXJtcyA8LSBhcF90b3BpY3MgJT4lCiAgZ3JvdXBfYnkodG9waWMpICU+JQogIHNsaWNlX21heChiZXRhLCBuID0gNikgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKHRvcGljLCAtYmV0YSkKCmFwX3RvcF90ZXJtcyAlPiUKICBtdXRhdGUodGVybSA9IHJlb3JkZXJfd2l0aGluKHRlcm0sIGJldGEsIHRvcGljKSkgJT4lCiAgZ2dwbG90KGFlcyhiZXRhLCB0ZXJtLCBmaWxsID0gZmFjdG9yKHRvcGljKSkpICsKICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IHRvcGljLCBzY2FsZXMgPSAiZnJlZSIpICsKICBzY2FsZV95X3Jlb3JkZXJlZCgpCmBgYApMREEgZW1wbG95cyB0aGUgVGVybSBGcmVxdWVuY3ktSW52ZXJzZSBEb2N1bWVudCBGcmVxdWVuY3kgKFRGLUlERikKbWV0cmljIHRvIGFzc2lnbiBwcm9iYWJpbGl0aWVzLgoKIyMjIDNiLiBGaXR0aW5nIGEgU3RydWN0dXJhbCBUb3BpYyBNb2RlbAoKQmFpbCAoMjAxOCkgYXJndWVzIHRoYXQgb25lIHJlYXNvbiBTVE0gaGFzIHJpc2luZyBpbiBwb3B1bGFyaXR5IGFuZCB1c2UgaXMgdGhhdCBpdCBlbXBsb3lzIG1ldGEgZGF0YSBhYm91dCBkb2N1bWVudHMgdG8gaW1wcm92ZSB0aGUgYXNzaWdubWVudCBvZiB3b3JkcyB0byB0b3BpY3MgaW4gYSBjb3JwdXMgYW5kIHRoYXQgY2FuIGJlIHVzZWQgdG8gZXhhbWluZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gY292YXJpYXRlcyBhbmQgZG9jdW1lbnRzLiBUaGlzIHdhcyB1c2VmdWwgZm9yIHRoaXMgcHJvamVjdCBpbiBjb25maXJtaW5nIHRoYXQgdG9waWNzIHJlbGF0ZWQgdG8gdGhlbWVzIHJldmVhbGVkIGluIHF1YWx0aXRhdGl2ZSBkYXRhLiAKCiMjIyMgVGhlIGBzdG1gIFBhY2thZ2UKCkJlZm9yZSBmaXR0aW5nIGFuIFNUTSBtb2RlbCwgaXQgd2FzIG5lY2Vzc2FyeSB0byBleHRyYWN0IHRoZSBmb2xsb3dpbmcgZWxlbWVudHM6CgpgYGB7ciBzdG0tZG9jc30KZG9jcyA8LSB0ZW1wJGRvY3VtZW50cyAKbWV0YSA8LSB0ZW1wJG1ldGEgCnZvY2FiIDwtIHRlbXAkdm9jYWIgCmBgYAoKVGhlc2UgZWxlbWVudHMgd2VyZSB0aGVuIHVzZWQgdG8gZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgc2FtZSB0b3BpY3MgZm9yICpLKiB0aGF0IHdlcmUgc3BlY2lmaWVkIGZvciB0aGUgTERBIHRvcGljIG1vZGVsLiAKCmBgYHtyIHN0bX0KaW50ZXJ2aWV3c19zdG0gPC0gc3RtKGRvY3VtZW50cz1kb2NzLCAKICAgICAgICAgZGF0YT1tZXRhLAogICAgICAgICB2b2NhYj12b2NhYiwgCiAgICAgICAgIEs9MjAsCiAgICAgICAgIG1heC5lbS5pdHM9MjUsCiAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSkKCmludGVydmlld3Nfc3RtCmBgYAoKVGhlIGZ1bmN0aW9uIGFsbG93cyBmb3Igdmlld2luZyB0aGUgbW9zdCBwcm9iYWJsZSB3b3JkcyBhc3NpZ25lZCB0byBlYWNoIHRvcGljLgoKYGBge3IgcGxvdC1zdG19CnBsb3QuU1RNKGludGVydmlld3Nfc3RtLCBuID0gNSkKYGBgCgoKYGBge3IgcGxvdH0KcGxvdChpbnRlcnZpZXdzX3N0bSwgbiA9IDUpCmBgYAoKIyMjIyMgCgojIyMgM2MuIEZpbmRpbmcgKksqCgpBcyBhbGx1ZGVkIHRvIGVhcmxpZXIsIHNlbGVjdGluZyB0aGUgbnVtYmVyIG9mIHRvcGljcyBmb3IgeW91ciBtb2RlbCBpcwphIG5vbi10cml2aWFsIGRlY2lzaW9uIGFuZCBjYW4gZHJhbWF0aWNhbGx5IGltcGFjdCB5b3VyIHJlc3VsdHMuIEJhaWwKKDIwMTgpIG5vdGVzIHRoYXQKCj4gKlRoZSByZXN1bHRzIG9mIHRvcGljIG1vZGVscyBzaG91bGQgbm90IGJlIG92ZXItaW50ZXJwcmV0ZWQgdW5sZXNzIHRoZQo+IHJlc2VhcmNoZXIgaGFzIHN0cm9uZyB0aGVvcmV0aWNhbCBhcHJpb3JpIGFib3V0IHRoZSBudW1iZXIgb2YgdG9waWNzCj4gaW4gYSBnaXZlbiBjb3JwdXMsIG9yIGlmIHRoZSByZXNlYXJjaGVyIGhhcyBjYXJlZnVsbHkgdmFsaWRhdGVkIHRoZQo+IHJlc3VsdHMgb2YgYSB0b3BpYyBtb2RlbCB1c2luZyBib3RoIHRoZSBxdWFudGl0YXRpdmUgYW5kIHF1YWxpdGF0aXZlCj4gdGVjaG5pcXVlcyBkZXNjcmliZWQgYWJvdmUuKgoKCiMjIyMgVGhlIEZpbmRUb3BpY3NOdW1iZXIgRnVuY3Rpb24KClRoZSBgbGRhdHVuaW5nYCBwYWNrYWdlIHdhcyB1c2VkIHRvIGFzc2lzdCB3aXRoIGZpbmRpbmcgSyB2YWx1ZS4KCmBgYHtyIGZpbmQtdG9waWMsIGV2YWw9RkFMU0V9CmtfbWV0cmljcyA8LSBGaW5kVG9waWNzTnVtYmVyKAogIGludGVydmlld3NfZHRtLAogIHRvcGljcyA9IHNlcSgxMCwgNzUsIGJ5ID0gNSksCiAgbWV0cmljcyA9ICJHcmlmZml0aHMyMDA0IiwKICBtZXRob2QgPSAiR2liYnMiLAogIGNvbnRyb2wgPSBsaXN0KCksCiAgbWMuY29yZXMgPSBOQSwKICByZXR1cm5fbW9kZWxzID0gRkFMU0UsCiAgdmVyYm9zZSA9IEZBTFNFLAogIGxpYnBhdGggPSBOVUxMCikKCkZpbmRUb3BpY3NOdW1iZXJfcGxvdChrX21ldHJpY3MpCmBgYAoKTm90ZSB0aGF0IHRoZSBgRmluZFRvcGljTnVtYmVycygpYCBmdW5jdGlvbiBjb250YWlucyB0aHJlZSBhZGRpdGlvbmFsCm1ldHJpY3MgZm9yIGNhbGN1bGF0aW5nIG1ldHJpY3MgdGhhdCBjYW4gYmUgdXNlZCB0byBlc3RpbWF0ZSB0aGUgbW9zdApwcmVmZXJhYmxlIG51bWJlciBvZiB0b3BpY3MgZm9yIExEQSBtb2RlbC4gV2UgdXNlZCB0aGUgR3JpZmZpdGhzMjAwNAptZXRyaWNzIGluY2x1ZGVkIGluIHRoZSBkZWZhdWx0IGV4YW1wbGUgYW5kIEkndmUgYWxzbyBmb3VuZCB0aGlzIHRvCnByb2R1Y2UgdGhlIG1vc3QgaW50ZXJwcmV0YWJsZSByZXN1bHRzIGFzIHNob3cgaW4gdGhlIGZpZ3VyZSBiZWxvdzoKCiFbXShpbWcva19tZXRyaWNzLnBuZyl7d2lkdGg9IjkwJSJ9CgpBcyBhIGdlbmVyYWwgcnVsZSBvZiB0aHVtYiBhbmQgb3Zlcmx5IHNpbXBsaXN0aWMgaGV1cmlzdGljLCB3ZSdyZQpsb29raW5nIGZvciBhbiBpbmZsZWN0aW9uIHBvaW50IGluIG91ciBwbG90IHdoaWNoIGluZGljYXRlcyBhbiBvcHRpbWFsCm51bWJlciBvZiB0b3BpY3MgdG8gc2VsZWN0IGZvciBhIHZhbHVlIG9mIEsuCgojIyMjIFRoZSBMREF2aXMgRXhwbG9yZXIKClRoZSBMREF2aXMgZXhwbG9yZXJlIHdhcyB1c2VkIHRvIGV4cG9yZSB0b3BpYyBhbmQgd29yZCBkaXN0cmlidXRpb25zLgoKYGBge3IgTERBdmlzfQp0b0xEQXZpcyhtb2QgPSBpbnRlcnZpZXdzX3N0bSwgZG9jcyA9IGRvY3MpCmBgYAoKIyMgNC4gRVhQTE9SRSAmIE1PREVMCgpTaWxnZSBhbmQgUm9iaW5zb24gKDIwMTgpIG5vdGUgdGhhdCBmaXR0aW5nIGF0IHRvcGljIG1vZGVsIGlzIHRoZSAiZWFzeQpwYXJ0LiIgVGhlIGhhcmQgcGFydCBpcyBtYWtpbmcgc2Vuc2Ugb2YgdGhlIG1vZGVsIHJlc3VsdHMgYW5kIHRoYXQgdGhlCnJlc3Qgb2YgdGhlIGFuYWx5c2lzIGludm9sdmVzIGV4cGxvcmluZyBhbmQgaW50ZXJwcmV0aW5nIHRoZSBtb2RlbCB1c2luZwphIHZhcmlldHkgb2YgYXBwcm9hY2hlcyB3aGljaCB3ZSdsbCB3YWxrdGhyb3VnaCBpbiBpbiB0aGlzIHNlY3Rpb24uCgpCYWlsICgyMDE4KSBjYXV0aW9ucywgaG93ZXZlciwgdGhhdDoKCj4gKi4uLnBvc3QtaG9jIGludGVycHJldGF0aW9uIG9mIHRvcGljIG1vZGVscyBpcyByYXRoZXIgZGFuZ2Vyb3VzLi4uIGFuZAo+IGNhbiBxdWlja2x5IGNvbWUgdG8gcmVzZW1ibGUgdGhlIHByb2Nlc3Mgb2YgInJlYWRpbmcgdGVhIGxlYXZlcywiIG9yCj4gZmluZGluZyBtZWFuaW5nIGluIHBhdHRlcm5zIHRoYXQgYXJlIGluIGZhY3QgcXVpdGUgYXJiaXRyYXJ5IG9yIGV2ZW4KPiByYW5kb20uKgoKIyMjIDRhLiBFeHBsb3JpbmcgQmV0YSBWYWx1ZXMKClRoZSA1IG1vc3QgbGlrZWx5IHRlcm1zIGFzc2lnbmVkIHRvIGVhY2ggdG9waWMgd2VyZSBleHBsb3JlZC4gVGhlc2UgcGVyLXRvcGljLXBlci13b3JkIHByb2JhYmlsaXRpZXMsIG9yICDOsiAoImJldGEiKSB2YWx1ZXMgcHJvdmlkZSB0aGUgcHJvYmFiaWxpdHkgb2YgYSB0ZXJtICh3b3JkKSBiZWxvbmdpbmcgdG8gYSB0b3BpYy4KCgpgYGB7ciB0ZXJtc30KdGVybXMoaW50ZXJ2aWV3c19sZGEsIDUpCmBgYAoKVG9waWMgMTAgKGV4cGVyaWVuY2UsIHRpbWUsIHBlb3BsZSwgY29vbCwKR2VybWFueSkgc2VlbXMgdG8gYmUgYWJvdXQgcGFydGljaXBhbnRzIGV4cGVyaWVuY2UgaW4gR2VybWFueS5UaGlzIGNvcnJlbGF0ZXMgd2l0aCB0aGUga2luZCBvZiBkYXRhIGZvdW5kIGluIHF1YWxpdGF0aXZlIHJlc2VhcmNoIG9uIHRoZSBzYW1lIGRhdGEuIAoKYGBge3IgdGlkeV9sZGF9Cgp0aWR5X2xkYSA8LSB0aWR5KGludGVydmlld3NfbGRhKQoKdGlkeV9sZGEKYGBgCgoKYGBge3IgdG9wX3Rlcm1zfQoKdG9wX3Rlcm1zIDwtIHRpZHlfbGRhICU+JQogIGdyb3VwX2J5KHRvcGljKSAlPiUKICBzbGljZV9tYXgoYmV0YSwgbiA9IDUsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZSh0b3BpYywgLWJldGEpCgp0b3BfdGVybXMgJT4lCiAgbXV0YXRlKHRlcm0gPSByZW9yZGVyX3dpdGhpbih0ZXJtLCBiZXRhLCB0b3BpYykpICU+JQogIGdyb3VwX2J5KHRvcGljLCB0ZXJtKSAlPiUgICAgCiAgYXJyYW5nZShkZXNjKGJldGEpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUKICBnZ3Bsb3QoYWVzKGJldGEsIHRlcm0sIGZpbGwgPSBhcy5mYWN0b3IodG9waWMpKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X3Jlb3JkZXJlZCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCA1IHRlcm1zIGluIGVhY2ggTERBIHRvcGljIiwKICAgICAgIHggPSBleHByZXNzaW9uKGJldGEpLCB5ID0gTlVMTCkgKwogIGZhY2V0X3dyYXAofiB0b3BpYywgbmNvbCA9IDQsIHNjYWxlcyA9ICJmcmVlIikKYGBgCgojIyMgCgojIyA1LiBDT01NVU5JQ0FURQoKQXMgU2lsZ2UgYW5kIFJvYmluc29uIG5vdGUgKDIwMTgpLCBmaXR0aW5nIHRoZSB0b3BpYyBtb2RlbCBpcyBlYXN5CnJlbGF0aXZlIHRvIHRoZSBtb3JlIGNoYWxsZW5naW5nIHdvcmsgb2YgaW50ZXJwcmV0aW5nIHRoZSBtb2RlbCByZXN1bHRzLgoKQ29tcGFyaW5nIHJlc3VsdHMgb2YgdGhlbWF0aWMgYW5hbHlzaXMgY29uZHVjdGVkIGJ5IHJlc2VhcmNoZXJzIHRvIHRvcGljCm1vZGVsaW5nIGNvbmR1Y3RlZCBpbiBSIGNhbiBwcm92aWRlIGluc2lnaHRzIGludG8gdGhlIGxpbWl0YXRpb25zIGFuZApiZW5lZml0cyBvZiBib3RoIGZvcm1zIG9mIHF1YWxpdGF0aXZlIHJlc2VhcmNoLiBBcyBCYWlsICgyMDE4KSB3YXJucywKIi4uLnBvc3QtaG9jIGludGVycHJldGF0aW9uIG9mIHRvcGljIG1vZGVscyBpcyByYXRoZXIgZGFuZ2Vyb3VzLi4uIGFuZApjYW4gcXVpY2tseSBjb21lIHRvIHJlc2VtYmxlIHRoZSBwcm9jZXNzIG9mICdyZWFkaW5nIHRlYSBsZWF2ZXMsJyBvcgpmaW5kaW5nIG1lYW5pbmcgaW4gcGF0dGVybnMgdGhhdCBhcmUgaW4gZmFjdCBxdWl0ZSBhcmJpdHJhcnkgb3IgZXZlbgpyYW5kb20uIgoKVGhlIHNhbWUgZGVzY3JpcHRpb24gY291bGQgYmUgYXBwbGllZCB0byB0aGVtYXRpYyBhbmFseXNpcywgYSBwcm9jZXNzCndoaWNoIGlzIGNyZWF0aXZlLCB0aW1lIGNvbnN1bWluZywgYW5kIGNhbiByZWZsZWN0IHRoZSBiaWFzZXMgb2YgdGhlCnJlc2VhcmNoZXJzLiBCeSBjb21wYXJpbmcgdGhlIHJlc3VsdHMgb2YgYm90aCBhcHByb2FjaGVzLCByZXNlYXJjaGVycwphbmQgcHJhY3RpdGlvbmVycyBjYW4gZ2FpbiBhIGRlZXBlciB1bmRlcnN0YW5kaW5nIG9mIHRoZSBkYXRhIGFuZCB0aGUKY29udGV4dCBpbiB3aGljaCBpdCB3YXMgY29sbGVjdGVkLiBUaGlzIGNhbiBsZWFkIHRvIHRyYW5zZm9ybWF0aXZlCmluc2lnaHRzIGludG8gaG93IHF1YWxpdGF0aXZlIHJlc2VhcmNoIGNhbiBiZSBjb25kdWN0ZWQgaW4gYSBtb3JlCnJpZ29yb3VzIGFuZCBzeXN0ZW1hdGljIG1hbm5lciwgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZm9yIHRoZSBjcmVhdGl2aXR5CmFuZCBzdWJqZWN0aXZpdHkgdGhhdCBhcmUgaW5oZXJlbnQgaW4gdGhpcyB0eXBlIG9mIHJlc2VhcmNoLiBNb3Jlb3ZlciwKcmVmbGVjdGluZyBvbiB0aGUgbGltaXRhdGlvbnMgYW5kIGJlbmVmaXRzIG9mIGJvdGggdGhlbWF0aWMgYW5hbHlzaXMgYW5kCnRvcGljIG1vZGVsaW5nIGNhbiBoZWxwIHJlc2VhcmNoZXJzIGFuZCBwcmFjdGl0aW9uZXJzIHRvIGlkZW50aWZ5IGFyZWFzCmZvciBpbXByb3ZlbWVudCBpbiB0aGVpciBvd24gcmVzZWFyY2ggcHJhY3RpY2VzLCBhcyB3ZWxsIGFzIHByb3ZpZGUKZ3VpZGFuY2UgZm9yIGZ1dHVyZSByZXNlYXJjaCBzdHVkaWVzLiBVbHRpbWF0ZWx5LCB0aGlzIGNhbiBsZWFkIHRvIG1vcmUKcm9idXN0IGFuZCBtZWFuaW5nZnVsIHF1YWxpdGF0aXZlIHJlc2VhcmNoIHRoYXQgY29udHJpYnV0ZXMgdG8gdGhlCmFkdmFuY2VtZW50IG9mIGtub3dsZWRnZSBpbiBhIHJhbmdlIG9mIGZpZWxkcy4KCgpJbml0aWFsIGZpbmRpbmdzIGZyb20gdGhlbWF0aWMgYW5hbHlzaXMgb2YgZm9jdXMgZ3JvdXAgZGF0YSBpbmRpY2F0ZWQKdGhhdAoKMS4pIFNlbGYtc2VsZWN0ZWQgZGlnaXRhbCBwcm9qZWN0cyBhbGxvd2VkIHBhcnRpY2lwYW50cyB0byBkZXZlbG9wCioqcHJvZmVzc2lvbmFsIGtub3dsZWRnZSoqIHJlbGF0ZWQgdG8gdGhlaXIgc3BlY2lmaWMgdGVhY2hpbmcgY29udGVudCwKY3VycmljdWx1bSwgYW5kIGNsYXNzcm9vbTsKCjIuKSBJbnRlcm5hdGlvbmFsIGltbWVyc2l2ZSBleHBlcmllbmNlIHdpdGggdGFyZ2V0ZWQgcHJvZmVzc2lvbmFsCmRldmVsb3BtZW50IHByb3ZpZGVkIGFuIG9wcG9ydHVuaXR5IGZvciAqKnJlZmxlY3Rpb25zIG9uCnBhbmRlbWljL3Bvc3QtcGFuZGVtaWMgaW5zdHJ1Y3Rpb24qKjsgYW5kCgozLikgVGVhY2hlcnMgcmVmbGVjdGVkIHRoYXQgdGhlIGV4cGVyaWVuY2UgaGFkIGFuIGltcGFjdCBvbiB0aGVpcgoqKnRlYWNoaW5nIGRpc3Bvc2l0aW9ucyBhbmQgcGxhbnMgZm9yIHRoZSBmdXR1cmUuKioKCkNvbXBhcmluZyB0b3BpY3MgdG8gaW50aXRpYWwgZmluZGluZ3MgZnJvbSB0aGVtYXRpYyBhbmFseXNpcyBzdWdnZXN0CnRoYXQgdG9waWMgYW5hbHlzaXMgcmVmbGVjdHMgZ2VuZXJhbCwgc3VwZXJmaWNpYWwgaW50ZXJwZXJldGF0aW9ucyBvZgp0aGUgZXhwZWlyZW5jZS4gV29yZHMgc3VjaCBhcyAiY29vbCIgImV4cGVyaWVuY2UiICJwZW9wbGUiICJmZWVsIgpyZWZsZWN0IGEgcG9zdGl2ZSwgYnV0IHN1cGVyZmljaWFsIGV4cGVyaWVuY2UgaW4gR2VybWFueS4gVGhlbWF0aWMKYW5hbHlzaXMsIGNvbmR1Y3RlZCBieSByZXNlYXJjaGVycyB3aXRoIHBlcnNvbmFsIHJlbGF0aW9uc2hpcHMgd2l0aApwYXJ0aWNpcGFudHMgc3VnZ2VzdHMgYSBudWFuY2VkLCBtb3JlIHNvcGhpc3RpY2F0ZWQgcmVhZGluZyBvZiB0aGUgZGF0YS4KVGhpcyBhbmF5bHNpcyByZWZsZWN0cyBvdXRjb21lcyBmcm9tIHRoZSBleHBlcmllbmNlIHdpdGggc3VnZ2VzdCBkZWVwCmNoYW5nZSBpbiB0ZWFjaGVyIHZhbHVlcyBhbmQgcHJhY3RpY2VzIHdoaWNoIGRvIG5vdCBzZWVtIHRvIGJlIHN1Z2dlc3RlZApmcm9tIHRvcGljIG1vZGVsaW5nLiBXaGlsZSB0aGUgdGV4dCBtaW5pZ24gYXBwcm9hY2ggYWxsb3dzIGZvciBhbmFseXNpcwpvZiBhIGxhcmdlIGNvcnB1cyBvZiBkYXRhLCBxdWFsaXRhdGl2ZSByZXNlZWFyY2ggZnJvbSBhIHRlYW0gb2ZmZXJzIGEKbW9yZSBpbi1kZXB0aCBhbmFseXNpcy4gVGhlIHR3byBoYXZlIHZhbHVlIHRvZ2V0aGVyIGluIHRoYXQgdG9waWMKbW9kZWxpbmcgY2FuIGJlIHVzZWQgd2l0aCBhIGxhcmdlciBjb3JwdXMgb2YgZGF0YSBhbmQgY2FuIG9mZmVyIGEKY29uZmlybWF0aW9uIG9mIHRoZSBnZW5lcmFsIGRpcmVjdGlvbiBvZiB0aGVtZXMgY3JlYXRlZCBpbiB0aGVtYXRpYwphbmFseXNpcy4gVGhlIHVzZSBvZiB0b3BpYyBtb2RlbGluZyBpbiBhZGRpdGlvbiB0byB0aGVtYXRpYyBhbmFseXNpcyBjYW4KcHJvdmlkZSBhIGZvcm0gb2YgdHJpYW5ndWxhdGlvbiB2YWx1YWJsZSB0byB0aGUgY3JlZGliaWxpdHkgb2YgYQpxdWFsaXRhdGl2ZSByZXNlYXJjaCBzdHVkeS4KCkV4cGVyaWVuY2UgZXhhbWluaW5nIHdoaWNoIHdvcmRzIHRlbmQgdG8gZm9sbG93IG90aGVycyBpbW1lZGlhdGVseSwgb3IKdGhhdCB0ZW5kIHRvIGNvLW9jY3VyIHdpdGhpbiB0aGUgc2FtZSBkb2N1bWVudHMuCgpDb21wYXJpbmcgcmVzdWx0cyBvZiB0aGVtYXRpYyBhbmFseXNpcyBjb25kdWN0ZWQgYnkgcmVzZWFyY2hlcnMgdG8gdG9waWMKbW9kZWxpbmcgY29uZHVjdGVkIGluIFIgY2FuIHByb3ZpZGUgaW5zaWdodHMgaW50byB0aGUgbGltaXRhdGlvbnMgYW5kCmJlbmVmaXRzIG9mIGJvdGggZm9ybXMgb2YgcXVhbGl0YXRpdmUgcmVzZWFyY2guIEFzIEJhaWwgKDIwMTgpIHdhcm5zLAoiLi4ucG9zdC1ob2MgaW50ZXJwcmV0YXRpb24gb2YgdG9waWMgbW9kZWxzIGlzIHJhdGhlciBkYW5nZXJvdXMuLi4gYW5kCmNhbiBxdWlja2x5IGNvbWUgdG8gcmVzZW1ibGUgdGhlIHByb2Nlc3Mgb2YgJ3JlYWRpbmcgdGVhIGxlYXZlcywnIG9yCmZpbmRpbmcgbWVhbmluZyBpbiBwYXR0ZXJucyB0aGF0IGFyZSBpbiBmYWN0IHF1aXRlIGFyYml0cmFyeSBvciBldmVuCnJhbmRvbS4iIFRoZSBzYW1lIGRlc2NyaXB0aW9uIGNvdWxkIGJlIGFwcGxpZWQgdG8gdGhlbWF0aWMgYW5hbHlzaXMsIGEKcHJvY2VzcyB3aGljaCBpcyBjcmVhdGl2ZSwgdGltZSBjb25zdW1pbmcsIGFuZCBjYW4gcmVmbGVjdCB0aGUgYmlhc2VzIG9mCnRoZSByZXNlYXJjaGVycy4gQnkgY29tcGFyaW5nIHRoZSByZXN1bHRzIG9mIGJvdGggYXBwcm9hY2hlcywKcmVzZWFyY2hlcnMgYW5kIHByYWN0aXRpb25lcnMgY2FuIGdhaW4gYSBkZWVwZXIgdW5kZXJzdGFuZGluZyBvZiB0aGUKZGF0YSBhbmQgdGhlIGNvbnRleHQgaW4gd2hpY2ggaXQgd2FzIGNvbGxlY3RlZC4gVGhpcyBjYW4gbGVhZCB0bwp0cmFuc2Zvcm1hdGl2ZSBpbnNpZ2h0cyBpbnRvIGhvdyBxdWFsaXRhdGl2ZSByZXNlYXJjaCBjYW4gYmUgY29uZHVjdGVkCmluIGEgbW9yZSByaWdvcm91cyBhbmQgc3lzdGVtYXRpYyBtYW5uZXIsIHdoaWxlIHN0aWxsIGFsbG93aW5nIGZvciB0aGUKY3JlYXRpdml0eSBhbmQgc3ViamVjdGl2aXR5IHRoYXQgYXJlIGluaGVyZW50IGluIHRoaXMgdHlwZSBvZiByZXNlYXJjaC4KTW9yZW92ZXIsIHJlZmxlY3Rpbmcgb24gdGhlIGxpbWl0YXRpb25zIGFuZCBiZW5lZml0cyBvZiBib3RoIHRoZW1hdGljCmFuYWx5c2lzIGFuZCB0b3BpYyBtb2RlbGluZyBjYW4gaGVscCByZXNlYXJjaGVycyBhbmQgcHJhY3RpdGlvbmVycyB0bwppZGVudGlmeSBhcmVhcyBmb3IgaW1wcm92ZW1lbnQgaW4gdGhlaXIgb3duIHJlc2VhcmNoIHByYWN0aWNlcywgYXMgd2VsbAphcyBwcm92aWRlIGd1aWRhbmNlIGZvciBmdXR1cmUgcmVzZWFyY2ggc3R1ZGllcy4gVWx0aW1hdGVseSwgdGhpcyBjYW4KbGVhZCB0byBtb3JlIHJvYnVzdCBhbmQgbWVhbmluZ2Z1bCBxdWFsaXRhdGl2ZSByZXNlYXJjaCB0aGF0IGNvbnRyaWJ1dGVzCnRvIHRoZSBhZHZhbmNlbWVudCBvZiBrbm93bGVkZ2UgaW4gYSByYW5nZSBvZiBmaWVsZHMuCgoKKipSZWZlcmVuY2VzKioKCkJyYXVuLCBWLiwgJiBDbGFya2UsIFYuICgyMDIyKS4gQ29uY2VwdHVhbCBhbmQgZGVzaWduIHRoaW5raW5nIGZvcgp0aGVtYXRpYyBhbmFseXNpcy4gUXVhbGl0YXRpdmUgUHN5Y2hvbG9neSwgOSgxKSwgMy0tMjYuCltodHRwczovL2RvaS5vcmcvMTAuMTAzNy9xdXAwMDAwMTk2XShodHRwczovL3BzeWNuZXQuYXBhLm9yZy9kb2kvMTAuMTAzNy9xdXAwMDAwMTk2KQoKQmFpbCwgQy4gKDIwMTgpLiBTdHJlbmd0aHMgYW5kIHdlYWtuZXNzZXMgb2YgdGV4dCBhcyBkYXRhLiBSZXRyaWV2ZWQKZnJvbQo8aHR0cHM6Ly9zaWNzcy5pby8yMDE5L21hdGVyaWFscy9kYXkzLXRleHQtYW5hbHlzaXMvdG9waWMtbW9kZWxpbmcvcm1hcmtkb3duL1RvcGljX01vZGVsaW5nLmh0bWw+CgpHaWxsaWVzLCBNLiwgTXVydGh5LCBELiwgQnJlbnRvbiwgSC4sICYgT2xhbml5YW4sIFIuICgyMDIyKS4gVGhlbWUgYW5kCnRvcGljOiBIb3cgcXVhbGl0YXRpdmUgcmVzZWFyY2ggYW5kIHRvcGljIG1vZGVsaW5nIGNhbiBiZSBicm91Z2h0CnRvZ2V0aGVyLiBhclhpdiBwcmVwcmludCBhclhpdjoyMjEwLjAwNzA3Lgo8aHR0cHM6Ly9kb2kub3JnLzEwLjQ4NTUwL2FyWGl2LjIyMTAuMDA3MDc+CgpTaWxnZSwgSi4sICYgUm9iaW5zb24sIEQuICgyMDE3KS4gVGV4dCBtaW5pbmcgd2l0aCBSOiBBIHRpZHkgYXBwcm9hY2guCk8nUmVpbGx5IE1lZGlhLCBJbmMuIFJldHJpZXZlZCBmcm9tOgo8aHR0cHM6Ly93d3cudGlkeXRleHRtaW5pbmcuY29tL3RvcGljbW9kZWxpbmcuaHRtbD4KCldpY2toYW0sIEguICYgR3JvbGVtdW5kLCBHLiAoMjAxNykuIFIgZm9yIERhdGEgU2NpZW5jZTogSW1wb3J0LCBUaWR5LApUcmFuc2Zvcm0sIFZpc3VhbGl6ZSwgYW5kIE1vZGVsIERhdGEuIE8nUmVpbGx5IE1lZGlhLCBJbmMuIFJldHJpZXZlZApmcm9tIDxodHRwczovL3I0ZHMuaGFkLmNvLm56Lz4KClwK