1 Datenauswertung

install.packages(c("ggpubr", "rstatix"))

1.1 Qualitative Daten

1.1.1 Verteilungen

Wir haben zuvor bereits mehrere Möglichkeiten gesehen, wie qualitative Daten dargestellt werden können.

Im Vordergrund bei der Betrachtung von Häufigkeiten liegen Balkendiagramme. Jedoch werden qualitative Daten auch häufig verwendet, um Daten zu gruppieren und somit verschiedene Gruppen von kontinuierlichen Daten darzustellen und zu unterscheiden.

1.1.1.1 Einzelne Variablen

Für Experimente und dessen Auswertung ist es wichtig, einen Überblick zu haben, wie viele Beobachtungen pro Gruppe vorhanden sind, damit die fortlaufenden Analysen nicht durch unbalancierte Gruppen (und der daraus resultierenden erhöhten Varianz) beeinflusst werden.

Betrachten wir ein typisches Experiment aus dem Agrarbereich. Der Datensatz npk beschreibt einen vollständigen Versuchsplan, bei dem der Effekt von Stickstoff, Phosphat und Kalium auf das Wachstum von Erbsen untersucht wurde. Für mehr Information schauen Sie unter ?npk nach.

library(tidyverse)
npk <- as_tibble(npk)
npk

Wir sehen, dass block, N, P und K Faktoren sind, wobei 1 für die Anwendung des Stoffes steht und 0 für dessen Abwesenheit.

Bei vollständigen Versuchsplanungen, wobei jeder Faktor entweder vorliegt oder nicht (0/1), gibt es insgesamt 2^X Möglichkeiten, wobei X die Anzahl der Faktoren ist. In diesem Fall liegen 3 Faktoren vor, sodass es 2^3=8 Kombinationen gibt.
Jede Kombination wurde in dreifacher Wiederholung getestet.

Verifizieren wir diesen Zusammenhang durch Balkendiagramme. Statt jeden Faktor einzeln zu betrachten, sollen die Faktoren gemeinsam (als Kombination) veranschaulicht werden. Hierzu müssen die Einträge z. B. durch str_c() kombiniert werden:

npk <- npk %>%
  mutate(kombination = str_c(N, P, K))
npk
ggplot(npk) +
  geom_bar(aes(kombination))

npk %>%
  group_by(kombination) %>%
  summarise(n = n())

Wir sehen, dass tatsächlich jedes Experiment in dreifacher Wiederholung durchgeführt wurde. Das ist besonders wichtig zu verifizieren, wenn die Datenmenge unübersichtlich bzw. sehr groß ist oder die Daten nicht selbst erhoben wurden.

1.1.1.2 Gemeinsame Verteilung

Für eine gemeinsame Verteilung von kontinuierlichen Variablen hatten wir Streudiagramme betrachtet. Bei qualitativen Variablen wird die Betrachung des gemeinsamen Auftretens von Variablen häufig vernachlässigt. Sie ist aber besonders dann wichtig, wenn viele Gruppen bzw. unbalancierte Daten vorliegen.

Für gemeinsame qualitative Variablen hatten wir bereits eine Visualisierung der paarweisen Häufigkeiten (Matrix-/Tabellenform) gesehen. Betrachten wir hierzu den Datensatz ?ToothGrowth, welcher das Zahnwachstum von Meerschweinchen bei verschiedenen täglichen Vitamin C Dosen und Zuführungsmethoden (Orangensaft oder Askorbinsäure) untersucht:

ToothGrowth <- as_tibble(ToothGrowth)
ToothGrowth <- ToothGrowth %>%
  mutate(dose = as.factor(dose))
ToothGrowth

Schauen wir nun, wie sich die beiden Faktoren supp und dose verteilen:

ggplot(ToothGrowth) +
  geom_count(aes(supp, dose))

ToothGrowth %>%
  count(supp, dose) %>%
ggplot(aes(supp, dose)) +
  geom_tile(aes(fill = n))

Es scheint, dass das Experiment balanciert ist und jede Kombination in derselben Wiederholung vorliegt.

Bei Umfrageergebnissen oder extern erhobenen Daten (ohne experimentellen Zusammenhang) kann das jedoch auch stark abweichen:

# Häufigkeitentabelle
diamonds %>% 
  count(cut, clarity)
diamonds %>%
  count(cut, clarity) %>%
  ggplot(aes(cut, clarity)) +
  geom_tile(aes(fill = n)) +
  scale_fill_gradient(low = "forestgreen", high = "tomato")

Hier sehen wir beispielsweise, dass Diamanten mit idealem Schliff häufig mit der Klarheit VS2 vorliegen und scheinbar ein Diamanten mit besserem Schliff häufiger verkauft werden bzw. in dem Datensatz vorhanden sind.

1.1.1.3 Zusammenhänge

Die Wichtigkeit der Gruppierung von kontinuierlichen Daten und dessen Durchführung hatten wir in dem letzten Kurs bereits beschrieben.

In dem vorherigen Abschnitt wurde beschrieben wie die gemeinsamen Häufigkeiten visualisiert und betrachtet werden können. An dieser Stelle kurz ergänzend, dass die Stärke des Zusammenhangs von qualitativen Variablen ebenfalls mit Cramers V berechnet werden kann. Hierzu wird eine Tabelle mit gemeinsamen Häufigkeiten benötigt:

library(rstatix)
anzahlen <- diamonds %>%
  count(cut, clarity) %>%
  pivot_wider(names_from = c(cut), values_from = n) %>%
  column_to_rownames(var = "clarity")
  anzahlen
  cramer_v(anzahlen)
[1] 0.1426645
  • Ein Wert von 0 zeigt hierbei keinen Zusammenhang an (Gleichverteilung) und ein Wert von 1 einen perfekten Zusammenhang.

  • Da der Wert in diesem Fall nahe bei 0 liegt, scheint es keinen besonderen Zusammenhang zwischen Schliff und Klarheit zu existieren.

1.2 Varianzanalyse

Der Hauptteil des heutigen Kurses soll die Durchführung der Varianzanalyse (ANOVA) darstellen.

Bei der ANOVA wird der Einfluss von einer (oder mehrerer) Faktoren (qualitative Variablen) auf eine kontinuierliche Variable betrachtet. Ein perfektes Beispiel hierfür ist der Datensatz npk, den wir zuvor gesehen haben. Hier liegen 3 Faktoren (Stickstoff, Phosphat und Kalium) vor, dessen Einfluss auf den Ertrag von Erbsen untersucht werden soll.

npk

Ebenso stellt der ToothGrowth Datensatz einen typischen Versuch dar, welcher mit ANOVA ausgewertet wird. Hierbei liegen ebenfalls Faktoren (Dosis und Zufuhrart) vor, dessen Einfluss auf eine kontinuierliche Variable (Länge) untersucht werden soll:

ToothGrowth

1.2.1 Ziel der Varianzanalyse

Das Ziel der Varianzanalyse ist es, herauszufinden, ob verschiedene Faktoren einen Einfluss auf eine Zielvariable haben.

Hierzu wird bei der ANOVA zunächst geprüft, ob es einen Unterschied zwischen den Gruppen gibt bzw. ob alle Gruppen im Mittel zu demselben Resultat (bezogen auf die Zielvariable) führen.

Das Hypothesenpaar prüft entsprechend, ob es mindestens eine Gruppe gibt, die statistisch signifikant von den anderen Gruppen abweicht:

  • H0: Die Gruppen sind alle gleich.

  • H1: Es gibt mindestens eine Gruppe, die von den anderen Gruppen abweicht.

Dementsprechend prüfen wir mit der ANOVA zunächst, ob es grundsätzlich “relevante” (abweichende) Ergebnisse gibt.

Falls die ANOVA ein signifikanten p-Wert liefert (z. B. kleiner als ⍺ = 0,05), dann können wir mit Hilfe eines Post-Hoc-Tests herausfinden, welche Gruppen abweichen.

Wir sehen gleich anhand von Beispielen, wie die ANOVA durchgeführt wird, was das bedeutet und wie diese zu interpretieren ist.

1.2.2 Voraussetzungen

Bevor eine ANOVA durchgeführt werden kann, muss geprüft werden, ob die Daten den Voraussetzungen der ANOVA genügen.

Falls die Daten zu sehr von den Voraussetzungen abweichen, verliert der ANOVA-Test an Aussagekraft, d. h. es ist fragwürdig/unsicher, ob dem Ergebnis zu trauen ist. Die Statistik soll uns absichern (im Wahrscheinlichkeitssinn), wo es statistisch signifikante Unterschiede gibt. Das ist bei fehlender Erfüllung der Voraussetzungen gestört.
Erinnern Sie sich an dieser Stelle auch zurück an die Bedeutung des p-Werts. Das Signifikanzniveau gibt stets an, wie sicher wir sind bzw. sein wollen.

Betrachten wir zunächst die Voraussetzungen der ANOVA und beginnen wir mit einem Faktor.

1.2.2.1 Unabhängigkeit der Beobachtungen

Die Beobachtungen müssen unabhängig und zufällig sein. Das kann nur bei der Durchführung des Experiments geschehen, d. h. die Testobjekte dürfen beispielsweise nicht wilkürlich oder mehrfach gemessen werden (außer bei zeitlichen Verläufen) und sollten zufällig (z. B. durch computer-gestützte randomisierte Zahlen/Auswahlen) ausgewählt werden.

1.2.2.2 Ausreißer

Für die übliche ANOVA sollten keine (extremen) Ausreißer in den Gruppen vorliegen. Die einfachste Möglichkeit zum Entdecken von Ausreißern sind Boxplots:

ggplot(ToothGrowth) +
  geom_boxplot(aes(supp, len, fill = supp))

  • Sie sehen ober-und unterhalb der Whisker keine Ausreißer

Falls Ausreißer vorhanden sind, können diese mit Hilfe von identify_outliers() aus rstatix entdeckt werden:

ToothGrowth %>%
  group_by(supp) %>%
  identify_outliers(len)
  • Ausreißer sind definiert als diejenigen, die mehr als das 1,5-fache von dem 1. bzw. 3. Quartil nach unten bzw. oben abweichen.

  • Extreme Ausreißer werden bei der identify_outliers() als die 3-fache Abweichung definiert.

Falls große Ausreißer vorhanden sind, sollte geprüft werden, ob diese Messfehler sind und ob diese mit in die Analyse hineinfließen sollten. Als Alternative zur ANOVA könnte der Kruskal-Walis-Test robuster sein, falls viele/starke Ausreißer vorhanden sind. Hierdurch wird insbesondere meistens die Normalverteilung gestört.

1.2.2.3 Normalverteilung

Falls die Ausreißer sich im Rahmen halten, können die Gruppen auf Normalverteilung getestet werden.

Hierzu können Boxplot und Histogramme nützlich sein:

ggplot(ToothGrowth, aes(len, after_stat(density))) +
  geom_histogram(binwidth = 4, fill = "steelblue") +
  geom_density() +
  facet_wrap(~supp)

  • Auf den ersten Blick ist es schwer zu deuten, ob die Daten normalverteilt sind.

  • Hierzu führen wir den Shapiro-Wilk-Test für jede Gruppe durch, um uns abzusichern.

ToothGrowth %>%
  group_by(supp) %>%
  shapiro_test(len)
  • Der Test suggeriert, dass bei einem Signifikanzniveau von 0,05 die Länge bezüglich der Askorbinsäuregruppe normalverteilt ist (p > ⍺, H0 wird nicht abgelehnt) jedoch die Orangensaftgruppe nicht normalverteil ist (p < ⍺, H0 wird abgelehnt).

Anmerkung:

  • Die ANOVA ist typischerweise relativ robust gegenüber der Verletzung der Voraussetzung der Normalverteilung der Gruppen.

  • Falls die Daten keiner Normalverteilung folgen, kann ebenfalls der Kruskal-Wallis-Test eine gute Alternative bieten.

  • Tatsächlich ist die Normalverteilung der Residuen des linearen Modells wichtiger. Das wollen wir hier aber nicht ausführen:

modell <- lm(len ~ supp, data = ToothGrowth)
shapiro_test(residuals(modell))

1.2.2.4 Varianzhomogenität

Schlussendlich sollte noch geprüft werden, ob die Varianz bezüglich der Gruppen homogen sind.

Das lässt sich aus dem Boxplot entnehmen (~ ähnlich hohe Boxen) und mit dem Levene-Test prüfen:

ToothGrowth %>%
  levene_test(len ~ supp)

Die Hypothesen des Levene-Tests besagen:

  • H0: Die Daten sind varianzhomogen

  • H1: Die Daten sind nicht varianzhomogen

Dementsprechend lehnen wir die Nullhypothese H0 nicht ab, da der p-Wert größer ist als 0,05. Somit sind die Gruppen (vermutlich) varianzhomogen.

1.2.3 ANOVA

Da die Daten varianzhomogen sind und es keine Ausreißer gibt, lässt sich die ANOVA anwenden, auch wenn die Daten nicht perfekt normalverteilt sind. In der Standardbibliothek von R gibt es hierfür die aov() Funktion:

ergebnis <- aov(len ~ supp, data = ToothGrowth)
summary(ergebnis)
            Df Sum Sq Mean Sq F value Pr(>F)  
supp         1    205  205.35   3.668 0.0604 .
Residuals   58   3247   55.98                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  • aov() erwartet als Eingabe eine Formel mit der Tilde ~

  • Links steht die abhängige (kontinuierliche) Variable, rechts die abhängigen Variablen (Faktoren)

  • Das Schema ist generell gleich wie die Erstellung eines Regressionsmodells mit lm()

Mit Hilfe von summary() sehen wir den p-Wert der ANOVA, welcher mit 0,06 größer als das typische Signifikanzniveau (0,05) ist.

Demnach nehmen wir an, dass es keinen signifikanten Unterschied in den Zufuhrmethoden gibt.

Alternativ können wir auch aus rstatix die Funktion anova_test() verwenden:

ToothGrowth %>%
  anova_test(len ~ supp)
ANOVA Table (type II tests)

  Effect DFn DFd     F    p p<.05   ges
1   supp   1  58 3.668 0.06       0.059

Testen wir ebenfalls die Dosis (dose) von Vitamin C auf den Einfluss des Zahnwachstums. Nehmen wir an, dass die ANOVA Voraussetzungen erfüllt wurden:

aov_ergebnis <- ToothGrowth %>%
  anova_test(len ~ dose)
aov_ergebnis
ANOVA Table (type II tests)

  Effect DFn DFd      F        p p<.05   ges
1   dose   2  57 67.416 9.53e-16     * 0.703
  • Der p-Wert ist sehr klein, d. h. mindestens eine Gruppe unterscheidet sich signifikant von den anderen.

  • Welche Gruppe das ist, lässt sich anhand eines Post-Hoc-Tests feststellen.

1.2.4 Post-Hoc-Test

Bei dem Post-Hoc-Test soll festgestellt werden, welche Gruppen sich signifikant unterscheiden, da die ANOVA nur suggeriert, ob sich eine Gruppe unterscheidet.

Da hierbei jedes Gruppenpaar separat getestet wird, müssen die p-Werte angepasst werden (p.adj), da sonst die Wahrscheinlichkeit steigt, dass sich der Test irrt (durch mehrfaches Testen).

Der beliebteste Post-Hoc-Test der einfachen ANOVA ist der Tukey-HSD-Test. Für die aov() Ergebnisse wird dieser wie folgt durchgeführt:

ergebnis <- aov(len ~ dose, data = ToothGrowth)
TukeyHSD(ergebnis)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = len ~ dose, data = ToothGrowth)

$dose
        diff       lwr       upr    p adj
1-0.5  9.130  5.901805 12.358195 0.00e+00
2-0.5 15.495 12.266805 18.723195 0.00e+00
2-1    6.365  3.136805  9.593195 4.25e-05
  • Die Unterschiede sind für alle Gruppen signifikant, da die p-Werte sehr klein sind.

  • Demnach kann davon ausgegangen werden, dass die Menge an Vitamin C einen signifikanten Einfluss auf das Wachstum der Zähne der Meerschweinchen hat.

Alternativ können wir das ebenfalls mit rstatix durchführen. Der Vorteil ist hierbei, dass sich die Tabelle mit den p-Werten direkt speichern lässt:

tukey <- ToothGrowth %>%
  tukey_hsd(len ~ dose)
tukey
# Ergebnis als Tabelle speichern:
# write_csv(tukey, "tukey_ergebnis.csv")

Das Ergebnis können Sie nun beispielsweise beliebig kürzen, um nur die relevante Information (signifikant, nicht signifikant) zu extrahieren:

# Gruppenvergleich
tukey_dose <- tukey %>%
    dplyr::select(group1, group2, p.adj)
tukey_dose
# Als Matrix:
tukey_dose %>%
    pivot_wider(names_from = group1, values_from = p.adj)

Das Ergebnis lässt sich auch anhand eines Boxplots nachvollziehbar darstellen:

# Setze die Position der Klammern:
tukey <- tukey %>%
  add_xy_position(x = "dose")
# Zeichne Boxplots für signifikante Gruppen:
ggplot(ToothGrowth) +
  geom_boxplot(aes(dose, len, fill = dose)) +
  ggpubr::stat_pvalue_manual(tukey, hide.ns = TRUE) + # fügt p-Werte hinzu
  theme(legend.position = NULL) +
  # Zusätzliche Information des Tests:
  labs(title = "Vitamin C fördert Zahnwachstum bei Meerschweinchen",
       subtitle = get_test_label(aov_ergebnis, detailed = TRUE),
       caption = get_pwc_label(tukey),
       x = "Vitamin C Dosis (mg/Tag)",
       y = "Zahnlänge (Länge der Odontoblasten)",
         fill = "Dosis")

1.2.5 Mehrere Faktoren

Zuvor haben wir lediglich einen Faktoren betrachtet. In der Realität sollen meist mehrere Faktoren zugleich getestet werden (z. B. Vitamin C Dosis und Zufuhrart). In diesem Fall bietet sich eine mehrfaktorielle ANOVA an.

Diese funktioniert wird prinzipiell sehr ähnlich zur einfaktoriellen ANOVA durchgeführt.

Betrachten wir erneut den ToothGrowth Datensatz und prüfen die Voraussetzungen nun für zwei Faktoren.

1.2.5.1 Ausreißer

ggplot(ToothGrowth) +
  geom_boxplot(aes(supp, len, fill = dose, color = len))

ToothGrowth %>%
  group_by(supp, dose) %>%
  identify_outliers(len)
  • Es liegen zwei Ausreißer vor. Das mag noch im Rahmen liegen

1.2.5.2 Normalverteilung

ToothGrowth %>%
  group_by(supp, dose) %>%
  shapiro_test(len)
  • Die p-Werte sind alle größer als das übliche Signifikanzniveau, sodass alle Gruppen normalverteilt sind.

1.2.5.3 Varianzhomogenität

ToothGrowth %>%
  levene_test(len ~ supp * dose)
  • Es ist wichtig, hierbei das *-Symbol zu verwenden, damit ebenfalls die Interaktion getestet wird.
  • Da der p-Wert über dem üblichen Signifikanzniveau liegt, nehmen wir die Varianzhomogenität an.

1.2.5.4 Zweifaktorielle ANOVA

Da alle Voraussetzungen erfüllt sind, kann die zweifaktorielle ANOVA durchgeführt werden:

zwei_faktor_aov <- ToothGrowth %>%
  anova_test(len ~ supp * dose)
zwei_faktor_aov
ANOVA Table (type II tests)

     Effect DFn DFd      F        p p<.05   ges
1      supp   1  54 15.572 2.31e-04     * 0.224
2      dose   2  54 92.000 4.05e-18     * 0.773
3 supp:dose   2  54  4.107 2.20e-02     * 0.132
  • Beachten Sie, dass bei diesem Modell das * für die Betrachtung der einzelnen unabhängigen Variablen als Haupteffekt sowie dessen Interaktion steht.

  • Das + Symbol betrachtet nur die unabhängigen Variablen ohne dessen Interaktion.

  • Das : Symbol betrachtet nur die Interaktion der unabhängigen Variablen ohne den Haupteffekt.

  • Sie sehen, dass alle Effekte (Haupteffekte sowie Interaktion) signifikant sind, d. h. es gibt innerhalb der einzelnen Gruppen signifikante Unterschiede sowie bei der gemeinsamen Betrachtung der Gruppen (Interaktion).

1.2.5.5 Post-Hoc-Test

Da die Interaktion signifikant ist, können wir den Effekt von dose für jede Stufe von supp in einer einfaktoriellen ANOVA betrachten:

ToothGrowth %>%
  group_by(supp) %>%
  anova_test(len ~ dose)
  • Wir sehen, dass der Haupteffekt von der Dosis auf die Zahnlänge signifikant war für beide Zufuhrarten.

Nun wollen wir wissen, welche der Gruppen sich unterscheiden:

ToothGrowth %>%
  group_by(supp) %>%
  tukey_hsd(len ~ dose)
  • Wir sehen, dass sich alle Gruppen signifikant unterscheiden (bzgl. der Zahnlange) außer der Vergleich von Orangensaft bei der Einnahme von 1mg zu 2mg Vitamin C am Tag.

  • Wenn wirklich jede Gruppe miteinander verglichen werden soll, kann das ebenfalls mit dem Tukey-HSD-Test durchgeführt werden. Hierbei sind die p-Werte allerdings etwas größer, da diese durch die höhere Testanzahl weiter korrigiert werden (p.adj):

ToothGrowth %>%
  tukey_hsd(len ~ supp * dose)

Wäre die Interaktion nicht signifikant, könnte dennoch mit paarweisen Tests (z. B. paarweisen t-Tests pairwise_t_test(), Tukey) nach Unterschieden in den Haupteffekten geschaut werden ohne die Interaktion (falls ein Haupteffekt signifikant ist).

Das entspricht dem, was wir bei der einfaktoriellen ANOVA bereits durchgeführt haben.

Falls man daran interessiert ist, verschiedene Gruppenaufteilungen miteinander zu vergleichen (z. B. Dosis 0.5/1mg/Tag gegen Dosis 2mg/Tag), dann bietet sich zum Beispiel die glht Funktion aus multcomp an. Siehe hierzu hier.

1.3 Alternative Tests zur (einfaktoriellen) ANOVA

An dieser Stelle eine Entscheidungshilfe, welcher Test bei der einfaktoriellen Analyse verwendet werden sollte:

Entscheidungsbaum ANOVA

1.3.1 Welch

Wenn die Bedingung der Varianzhomogenität der Gruppen bei der einfaktoriellen ANOVA nicht eingehalten ist, kann der Welch-Test als robustere ANOVA-Variante verwendet werden. Die einfache ANOVA verliert sehr viel Aussagekraft, wenn die Daten nicht varianzhomogen sin.

Der Welch-Test wird analog durchgeführt und meistens mit den Post-Hoc-Tests von Games-Howell oder dem paarweisen t-Test kombiniert, da diese bei Varianzinhomogenität robuster sind:

welch_ergebnis <- ToothGrowth %>%
  welch_anova_test(len ~ dose)
welch_ergebnis

Die möglichen Post-Hoc-Tests lassen sich ebenso analog wie zuvor verwenden:

# Games-Howell:
games_howell_ergebnis <- ToothGrowth %>%
  games_howell_test(len ~ dose)
games_howell_ergebnis
# t-Tests: Vorsicht: der Parameter pool.sd = FALSE ist wichtig,
# damit keine Varianzhomogenität vorausgesetzt ist
paarw_t_test_ergebnis <- ToothGrowth %>%
  pairwise_t_test(len ~ dose, pool.sd = FALSE)
paarw_t_test_ergebnis
  • Die p-Werte unterscheiden sich leicht, geben aber dieselbe Tendenz an.

1.3.2 Kruskal-Wallis

Falls die Voraussetzungen der einfaktoriellen ANOVA gänzlich nicht gegeben sind (bzw. die Daten nicht annähernd normalverteilt), kann der nicht-parametrische Kruskal-Wallis-Test durchgeführt werden. Als Post-Hoc-Test wird nach dem Kruskal-Wallis-Test entweder der Wilcoxon-Test oder der Dunn-Test durchgeführt:

# Kruskal-Wallis-Test:
ToothGrowth %>%
  kruskal_test(len ~ dose)
# Dunn-Test:
ToothGrowth %>%
  dunn_test(len ~ dose)
# Wilcoxon-Test:
ToothGrowth %>%
  wilcox_test(len ~ dose)
  • Die Interpretation der Testergebnisse folgt der einfachen ANOVA.

1.3.3 Mehrfaktoren

Falls die Voraussetzungen der Daten der zweifaktoriellen ANOVA nicht genügen, gibt es mehrere Möglichkeiten.

  • Es gibt keinen alternativen nicht-parametrischen Test für mehrere Faktoren, der ebenfalls die Interaktion dieser betrachten kann.

  • Sofern die Normalverteilung nicht gegeben ist, kann die zweifaktorielle ANOVA meist dennoch verwendet werden, wobei die Ergebnisse ggf. unter Vorbehalt zu interpretieren sind.

  • Falls die Interaktion eine untergeordnete Rolle spielt, ließe sich auch für jeden Faktor eine einfaktorielle ANOVA durchführen, um innerhalb der einzelnen Gruppen Unterschiede zu finden.

  • Falls es viele Ausreißer gibt oder die Varianzhomogenität nicht gegeben ist, bietet es sich an, Korrekturmethoden zu verwenden und die Daten zu transformieren (z. B. log-Transformation, Box-Cox-Transofmration), sodass diese varianzhomogen (und normalverteilt) sind.
    Für eine typische Korrekturmethode siehe beispielsweise hier.

  • Alternativ kann auch ein robustes Regressionsmodell erstellt werden.

1.4 Andere ANOVA-Tests

Neben der einfachen ANOVA gibt es noch weitere Arten der ANOVA, die für spezifische Anwendungsfälle ausgelegt sind.

1.4.1 Wiederholte Messungen

Wenn dieselben Untersuchungsobjekte zu mehreren Zeitpunkten gemessen wurden, wird eine spezielle ANOVA für wiederholte Messungen verwendet. Das rstatix Paket bietet mit anova_test() ebenfalls Funktionalität für die ANOVA für wiederholte Messungen.

1.4.2 Mixed ANOVA

Wenn dieselben Untersuchungsobjekte zu mehreren Zeitpunkten gemessen wurden und zusätzlich ein weiterer Faktor betrachtet werden soll, wird eine gemischte ANOVA verwendet. Auch diese Funktionalität bietet anova_test() für gemischte ANOVA Designs.

1.4.3 ANCOVA

Wenn eine einfache ANOVA durchgeführt werden soll, jedoch zusätzlich für eine kontinuierliche Variable (Kovariate) die ANOVA korrigiert werden soll, wird die ANCOVA verwendet. Für mehr Information zur ANCOVA siehe hier.

1.4.4 MANOVA

Alle vorherigen ANOVA Verfahren hatten gemeinsam, dass nur eine kontinuierliche Variable als abhängige Variable betrachtet wurde.

Falls gleichzeitig mehrere kontinuierliche Variable in einer ANOVA als Zielvariable betrachtet werden sollen, kann eine MANOVA (multivariate ANOVA) verwendet werden anstelle der Durchführung von mehreren einfachen ANOVAs.

Für mehr Information zur MANOVA siehe hier.

Bedenken Sie, dass es in R meistens mehrere Möglichkeiten und Pakete gibt, dieselben Analysen durchzuführen.

Falls Sie spezielle Tests/Verfahren verwenden wollen, sollten Sie stets eine Suchmaschine aufsuchen und nach einem passenden externen Paket suchen. Für statistische Tests sind beispielsweise car, MASS oder multcomp prominente Pakete.

Bedenken Sie auch, dass jeder statistische Test verschiedene Voraussetzungen hat und wählen Sie so den passenden Test aus. Auch die verschiedenen ANOVA-Verfahren haben verschiedene Voraussetzungen.

2 Aufgaben

In diesem Teil wollen wir den Datensatz npk auswerten:

library(tidyverse)
npk <- as_tibble(npk)
npk

Wie bereits erläutert handelt es sich bei dem Datensatz um ein typischen vollständigen Versuchsplan aus dem Bereich der Agrarwissenschaften. Der Datzensatz beschreibt den Einfluss des Einsatzes von Stickstoff (N), Phosphat (P) und Kalium (K) auf den Ertrag von Erbsen (yield).

2.1 Übungsaufgaben

  1. Werten Sie den Datzensatz npk mit einer passenden ANOVA aus.

    1. Verschaffen Sie sich eine (visuelle/statistische) Übersicht über die Daten.

    2. Prüfen Sie die Voraussetzungen der einfachen ANOVA.

    3. Wenden Sie das passende ANOVA-Modell an.

    4. Interpretieren Sie die Ergebnisse.

LS0tCnRpdGxlOiAiU3RhdGlzdGlrIHVuZCBEYXRhIFNjaWVuY2UgLSBWYXJpYW56YW5hbHlzZSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogeWVzCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCiMgRGF0ZW5hdXN3ZXJ0dW5nCgpgYGB7ciwgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcyhjKCJnZ3B1YnIiLCAicnN0YXRpeCIpKQpgYGAKCiMjIFF1YWxpdGF0aXZlIERhdGVuCgojIyMgVmVydGVpbHVuZ2VuCgpXaXIgaGFiZW4genV2b3IgYmVyZWl0cyBtZWhyZXJlIE3DtmdsaWNoa2VpdGVuIGdlc2VoZW4sIHdpZSBxdWFsaXRhdGl2ZQpEYXRlbiBkYXJnZXN0ZWxsdCB3ZXJkZW4ga8O2bm5lbi4KCkltIFZvcmRlcmdydW5kIGJlaSBkZXIgQmV0cmFjaHR1bmcgdm9uIEjDpHVmaWdrZWl0ZW4gbGllZ2VuCkJhbGtlbmRpYWdyYW1tZS4gSmVkb2NoIHdlcmRlbiBxdWFsaXRhdGl2ZSBEYXRlbiBhdWNoIGjDpHVmaWcgdmVyd2VuZGV0LAp1bSBEYXRlbiB6dSBncnVwcGllcmVuIHVuZCBzb21pdCB2ZXJzY2hpZWRlbmUgR3J1cHBlbiB2b24Ka29udGludWllcmxpY2hlbiBEYXRlbiBkYXJ6dXN0ZWxsZW4gdW5kIHp1IHVudGVyc2NoZWlkZW4uCgojIyMjIEVpbnplbG5lIFZhcmlhYmxlbgoKRsO8ciBFeHBlcmltZW50ZSB1bmQgZGVzc2VuIEF1c3dlcnR1bmcgaXN0IGVzIHdpY2h0aWcsIGVpbmVuIMOcYmVyYmxpY2sgenUKaGFiZW4sIHdpZSB2aWVsZSBCZW9iYWNodHVuZ2VuIHBybyBHcnVwcGUgdm9yaGFuZGVuIHNpbmQsIGRhbWl0IGRpZQpmb3J0bGF1ZmVuZGVuIEFuYWx5c2VuIG5pY2h0IGR1cmNoIHVuYmFsYW5jaWVydGUgR3J1cHBlbiAodW5kIGRlciBkYXJhdXMKcmVzdWx0aWVyZW5kZW4gZXJow7ZodGVuIFZhcmlhbnopIGJlZWluZmx1c3N0IHdlcmRlbi4KCkJldHJhY2h0ZW4gd2lyIGVpbiB0eXBpc2NoZXMgRXhwZXJpbWVudCBhdXMgZGVtIEFncmFyYmVyZWljaC4gRGVyCkRhdGVuc2F0eiBgbnBrYCBiZXNjaHJlaWJ0IGVpbmVuIHZvbGxzdMOkbmRpZ2VuIFZlcnN1Y2hzcGxhbiwgYmVpIGRlbSBkZXIKRWZmZWt0IHZvbiBTdGlja3N0b2ZmLCBQaG9zcGhhdCB1bmQgS2FsaXVtIGF1ZiBkYXMgV2FjaHN0dW0gdm9uIEVyYnNlbgp1bnRlcnN1Y2h0IHd1cmRlLiBGw7xyIG1laHIgSW5mb3JtYXRpb24gc2NoYXVlbiBTaWUgdW50ZXIgYD9ucGtgIG5hY2guCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCm5wayA8LSBhc190aWJibGUobnBrKQpucGsKYGBgCgpXaXIgc2VoZW4sIGRhc3MgYGJsb2NrYCwgYE5gLCBgUGAgdW5kIGBLYCBGYWt0b3JlbiBzaW5kLCB3b2JlaSAxIGbDvHIgZGllCkFud2VuZHVuZyBkZXMgU3RvZmZlcyBzdGVodCB1bmQgMCBmw7xyIGRlc3NlbiBBYndlc2VuaGVpdC4KCkJlaSB2b2xsc3TDpG5kaWdlbiBWZXJzdWNoc3BsYW51bmdlbiwgd29iZWkgamVkZXIgRmFrdG9yIGVudHdlZGVyCnZvcmxpZWd0IG9kZXIgbmljaHQgKDAvMSksIGdpYnQgZXMgaW5zZ2VzYW10IDJcXlggTcO2Z2xpY2hrZWl0ZW4sIHdvYmVpIFgKZGllIEFuemFobCBkZXIgRmFrdG9yZW4gaXN0LiBJbiBkaWVzZW0gRmFsbCBsaWVnZW4gMyBGYWt0b3JlbiB2b3IsCnNvZGFzcyBlcyAyXF4zPTggS29tYmluYXRpb25lbiBnaWJ0LlwKSmVkZSBLb21iaW5hdGlvbiB3dXJkZSBpbiBkcmVpZmFjaGVyIFdpZWRlcmhvbHVuZyBnZXRlc3RldC4KClZlcmlmaXppZXJlbiB3aXIgZGllc2VuIFp1c2FtbWVuaGFuZyBkdXJjaCBCYWxrZW5kaWFncmFtbWUuIFN0YXR0IGplZGVuCkZha3RvciBlaW56ZWxuIHp1IGJldHJhY2h0ZW4sIHNvbGxlbiBkaWUgRmFrdG9yZW4gZ2VtZWluc2FtIChhbHMKS29tYmluYXRpb24pIHZlcmFuc2NoYXVsaWNodCB3ZXJkZW4uIEhpZXJ6dSBtw7xzc2VuIGRpZSBFaW50csOkZ2Ugei4gQi4KZHVyY2ggYHN0cl9jKClgIGtvbWJpbmllcnQgd2VyZGVuOgoKYGBge3J9Cm5wayA8LSBucGsgJT4lCiAgbXV0YXRlKGtvbWJpbmF0aW9uID0gc3RyX2MoTiwgUCwgSykpCm5wawpnZ3Bsb3QobnBrKSArCiAgZ2VvbV9iYXIoYWVzKGtvbWJpbmF0aW9uKSkKbnBrICU+JQogIGdyb3VwX2J5KGtvbWJpbmF0aW9uKSAlPiUKICBzdW1tYXJpc2UobiA9IG4oKSkKYGBgCgpXaXIgc2VoZW4sIGRhc3MgdGF0c8OkY2hsaWNoIGplZGVzIEV4cGVyaW1lbnQgaW4gZHJlaWZhY2hlciBXaWVkZXJob2x1bmcKZHVyY2hnZWbDvGhydCB3dXJkZS4gRGFzIGlzdCBiZXNvbmRlcnMgd2ljaHRpZyB6dSB2ZXJpZml6aWVyZW4sIHdlbm4gZGllCkRhdGVubWVuZ2UgdW7DvGJlcnNpY2h0bGljaCBiencuIHNlaHIgZ3Jvw58gaXN0IG9kZXIgZGllIERhdGVuIG5pY2h0CnNlbGJzdCBlcmhvYmVuIHd1cmRlbi4KCiMjIyMgR2VtZWluc2FtZSBWZXJ0ZWlsdW5nCgpGw7xyIGVpbmUgZ2VtZWluc2FtZSBWZXJ0ZWlsdW5nIHZvbiBrb250aW51aWVybGljaGVuIFZhcmlhYmxlbiBoYXR0ZW4gd2lyClN0cmV1ZGlhZ3JhbW1lIGJldHJhY2h0ZXQuIEJlaSBxdWFsaXRhdGl2ZW4gVmFyaWFibGVuIHdpcmQgZGllCkJldHJhY2h1bmcgZGVzIGdlbWVpbnNhbWVuIEF1ZnRyZXRlbnMgdm9uIFZhcmlhYmxlbiBow6R1ZmlnCnZlcm5hY2hsw6Rzc2lndC4gU2llIGlzdCBhYmVyIGJlc29uZGVycyBkYW5uIHdpY2h0aWcsIHdlbm4gdmllbGUgR3J1cHBlbgpiencuIHVuYmFsYW5jaWVydGUgRGF0ZW4gdm9ybGllZ2VuLgoKRsO8ciBnZW1laW5zYW1lIHF1YWxpdGF0aXZlIFZhcmlhYmxlbiBoYXR0ZW4gd2lyIGJlcmVpdHMgZWluZQpWaXN1YWxpc2llcnVuZyBkZXIgcGFhcndlaXNlbiBIw6R1Zmlna2VpdGVuIChNYXRyaXgtL1RhYmVsbGVuZm9ybSkKZ2VzZWhlbi4gQmV0cmFjaHRlbiB3aXIgaGllcnp1IGRlbiBEYXRlbnNhdHogYD9Ub290aEdyb3d0aGAsIHdlbGNoZXIgZGFzClphaG53YWNoc3R1bSB2b24gTWVlcnNjaHdlaW5jaGVuIGJlaSB2ZXJzY2hpZWRlbmVuIHTDpGdsaWNoZW4gVml0YW1pbiBDCkRvc2VuIHVuZCBadWbDvGhydW5nc21ldGhvZGVuIChPcmFuZ2Vuc2FmdCBvZGVyIEFza29yYmluc8OkdXJlKQp1bnRlcnN1Y2h0OgoKYGBge3J9ClRvb3RoR3Jvd3RoIDwtIGFzX3RpYmJsZShUb290aEdyb3d0aCkKVG9vdGhHcm93dGggPC0gVG9vdGhHcm93dGggJT4lCiAgbXV0YXRlKGRvc2UgPSBhcy5mYWN0b3IoZG9zZSkpClRvb3RoR3Jvd3RoCmBgYAoKU2NoYXVlbiB3aXIgbnVuLCB3aWUgc2ljaCBkaWUgYmVpZGVuIEZha3RvcmVuIGBzdXBwYCB1bmQgYGRvc2VgCnZlcnRlaWxlbjoKCmBgYHtyfQpnZ3Bsb3QoVG9vdGhHcm93dGgpICsKICBnZW9tX2NvdW50KGFlcyhzdXBwLCBkb3NlKSkKVG9vdGhHcm93dGggJT4lCiAgY291bnQoc3VwcCwgZG9zZSkgJT4lCmdncGxvdChhZXMoc3VwcCwgZG9zZSkpICsKICBnZW9tX3RpbGUoYWVzKGZpbGwgPSBuKSkKYGBgCgpFcyBzY2hlaW50LCBkYXNzIGRhcyBFeHBlcmltZW50IGJhbGFuY2llcnQgaXN0IHVuZCBqZWRlIEtvbWJpbmF0aW9uIGluCmRlcnNlbGJlbiBXaWVkZXJob2x1bmcgdm9ybGllZ3QuCgpCZWkgVW1mcmFnZWVyZ2Vibmlzc2VuIG9kZXIgZXh0ZXJuIGVyaG9iZW5lbiBEYXRlbiAob2huZSBleHBlcmltZW50ZWxsZW4KWnVzYW1tZW5oYW5nKSBrYW5uIGRhcyBqZWRvY2ggYXVjaCBzdGFyayBhYndlaWNoZW46CgpgYGB7cn0KIyBIw6R1Zmlna2VpdGVudGFiZWxsZQpkaWFtb25kcyAlPiUgCiAgY291bnQoY3V0LCBjbGFyaXR5KQpkaWFtb25kcyAlPiUKICBjb3VudChjdXQsIGNsYXJpdHkpICU+JQogIGdncGxvdChhZXMoY3V0LCBjbGFyaXR5KSkgKwogIGdlb21fdGlsZShhZXMoZmlsbCA9IG4pKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiZm9yZXN0Z3JlZW4iLCBoaWdoID0gInRvbWF0byIpCmBgYAoKSGllciBzZWhlbiB3aXIgYmVpc3BpZWxzd2Vpc2UsIGRhc3MgRGlhbWFudGVuIG1pdCBpZGVhbGVtIFNjaGxpZmYgaMOkdWZpZwptaXQgZGVyIEtsYXJoZWl0IGBWUzJgIHZvcmxpZWdlbiB1bmQgc2NoZWluYmFyIGVpbiBEaWFtYW50ZW4gbWl0CmJlc3NlcmVtIFNjaGxpZmYgaMOkdWZpZ2VyIHZlcmthdWZ0IHdlcmRlbiBiencuIGluIGRlbSBEYXRlbnNhdHoKdm9yaGFuZGVuIHNpbmQuCgojIyMjIFp1c2FtbWVuaMOkbmdlCgpEaWUgV2ljaHRpZ2tlaXQgZGVyIEdydXBwaWVydW5nIHZvbiBrb250aW51aWVybGljaGVuIERhdGVuIHVuZCBkZXNzZW4KRHVyY2hmw7xocnVuZyBoYXR0ZW4gd2lyIGluIGRlbSBsZXR6dGVuIEt1cnMgYmVyZWl0cyBiZXNjaHJpZWJlbi4KCkluIGRlbSB2b3JoZXJpZ2VuIEFic2Nobml0dCB3dXJkZSBiZXNjaHJpZWJlbiB3aWUgZGllIGdlbWVpbnNhbWVuCkjDpHVmaWdrZWl0ZW4gdmlzdWFsaXNpZXJ0IHVuZCBiZXRyYWNodGV0IHdlcmRlbiBrw7ZubmVuLiBBbiBkaWVzZXIgU3RlbGxlCmt1cnogZXJnw6RuemVuZCwgZGFzcyBkaWUgU3TDpHJrZSBkZXMgWnVzYW1tZW5oYW5ncyB2b24gcXVhbGl0YXRpdmVuClZhcmlhYmxlbiBlYmVuZmFsbHMgbWl0IENyYW1lcnMgViBiZXJlY2huZXQgd2VyZGVuIGthbm4uIEhpZXJ6dSB3aXJkCmVpbmUgVGFiZWxsZSBtaXQgZ2VtZWluc2FtZW4gSMOkdWZpZ2tlaXRlbiBiZW7DtnRpZ3Q6CgpgYGB7cn0KbGlicmFyeShyc3RhdGl4KQphbnphaGxlbiA8LSBkaWFtb25kcyAlPiUKICBjb3VudChjdXQsIGNsYXJpdHkpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjKGN1dCksIHZhbHVlc19mcm9tID0gbikgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKHZhciA9ICJjbGFyaXR5IikKICBhbnphaGxlbgogIGNyYW1lcl92KGFuemFobGVuKQpgYGAKCi0gICBFaW4gV2VydCB2b24gMCB6ZWlndCBoaWVyYmVpIGtlaW5lbiBadXNhbW1lbmhhbmcgYW4KICAgIChHbGVpY2h2ZXJ0ZWlsdW5nKSB1bmQgZWluIFdlcnQgdm9uIDEgZWluZW4gcGVyZmVrdGVuIFp1c2FtbWVuaGFuZy4KCi0gICBEYSBkZXIgV2VydCBpbiBkaWVzZW0gRmFsbCBuYWhlIGJlaSAwIGxpZWd0LCBzY2hlaW50IGVzIGtlaW5lbgogICAgYmVzb25kZXJlbiBadXNhbW1lbmhhbmcgendpc2NoZW4gU2NobGlmZiB1bmQgS2xhcmhlaXQgenUgZXhpc3RpZXJlbi4KCiMjIFZhcmlhbnphbmFseXNlCgpEZXIgSGF1cHR0ZWlsIGRlcyBoZXV0aWdlbiBLdXJzZXMgc29sbCBkaWUgRHVyY2hmw7xocnVuZyBkZXIKVmFyaWFuemFuYWx5c2UgKEFOT1ZBKSBkYXJzdGVsbGVuLgoKQmVpIGRlciBBTk9WQSB3aXJkIGRlciBFaW5mbHVzcyB2b24gZWluZXIgKG9kZXIgbWVocmVyZXIpIEZha3RvcmVuCihxdWFsaXRhdGl2ZSBWYXJpYWJsZW4pIGF1ZiBlaW5lIGtvbnRpbnVpZXJsaWNoZSBWYXJpYWJsZSBiZXRyYWNodGV0LgpFaW4gcGVyZmVrdGVzIEJlaXNwaWVsIGhpZXJmw7xyIGlzdCBkZXIgRGF0ZW5zYXR6IGBucGtgLCBkZW4gd2lyIHp1dm9yCmdlc2VoZW4gaGFiZW4uIEhpZXIgbGllZ2VuIDMgRmFrdG9yZW4gKFN0aWNrc3RvZmYsIFBob3NwaGF0IHVuZCBLYWxpdW0pCnZvciwgZGVzc2VuIEVpbmZsdXNzIGF1ZiBkZW4gRXJ0cmFnIHZvbiBFcmJzZW4gdW50ZXJzdWNodCB3ZXJkZW4gc29sbC4KCmBgYHtyfQpucGsKYGBgCgpFYmVuc28gc3RlbGx0IGRlciBgVG9vdGhHcm93dGhgIERhdGVuc2F0eiBlaW5lbiB0eXBpc2NoZW4gVmVyc3VjaCBkYXIsCndlbGNoZXIgbWl0IEFOT1ZBIGF1c2dld2VydGV0IHdpcmQuIEhpZXJiZWkgbGllZ2VuIGViZW5mYWxscyBGYWt0b3JlbgooRG9zaXMgdW5kIFp1ZnVocmFydCkgdm9yLCBkZXNzZW4gRWluZmx1c3MgYXVmIGVpbmUga29udGludWllcmxpY2hlClZhcmlhYmxlIChMw6RuZ2UpIHVudGVyc3VjaHQgd2VyZGVuIHNvbGw6CgpgYGB7cn0KVG9vdGhHcm93dGgKYGBgCgojIyMgWmllbCBkZXIgVmFyaWFuemFuYWx5c2UKCkRhcyBaaWVsIGRlciBWYXJpYW56YW5hbHlzZSBpc3QgZXMsIGhlcmF1c3p1ZmluZGVuLCBvYiB2ZXJzY2hpZWRlbmUKRmFrdG9yZW4gZWluZW4gRWluZmx1c3MgYXVmIGVpbmUgWmllbHZhcmlhYmxlIGhhYmVuLgoKSGllcnp1IHdpcmQgYmVpIGRlciBBTk9WQSB6dW7DpGNoc3QgZ2VwcsO8ZnQsIG9iIGVzIGVpbmVuIFVudGVyc2NoaWVkCnp3aXNjaGVuIGRlbiBHcnVwcGVuIGdpYnQgYnp3LiBvYiBhbGxlIEdydXBwZW4gaW0gTWl0dGVsIHp1IGRlbXNlbGJlbgpSZXN1bHRhdCAoYmV6b2dlbiBhdWYgZGllIFppZWx2YXJpYWJsZSkgZsO8aHJlbi4KCkRhcyBIeXBvdGhlc2VucGFhciBwcsO8ZnQgZW50c3ByZWNoZW5kLCBvYiBlcyBtaW5kZXN0ZW5zIGVpbmUgR3J1cHBlCmdpYnQsIGRpZSBzdGF0aXN0aXNjaCBzaWduaWZpa2FudCB2b24gZGVuIGFuZGVyZW4gR3J1cHBlbiBhYndlaWNodDoKCi0gICBIMDogRGllIEdydXBwZW4gc2luZCBhbGxlIGdsZWljaC4KCi0gICBIMTogRXMgZ2lidCBtaW5kZXN0ZW5zIGVpbmUgR3J1cHBlLCBkaWUgdm9uIGRlbiBhbmRlcmVuIEdydXBwZW4KICAgIGFid2VpY2h0LgoKRGVtZW50c3ByZWNoZW5kIHByw7xmZW4gd2lyIG1pdCBkZXIgQU5PVkEgenVuw6RjaHN0LCBvYiBlcyBncnVuZHPDpHR6bGljaAoicmVsZXZhbnRlIiAoYWJ3ZWljaGVuZGUpIEVyZ2Vibmlzc2UgZ2lidC4KCkZhbGxzIGRpZSBBTk9WQSBlaW4gc2lnbmlmaWthbnRlbiBwLVdlcnQgbGllZmVydCAoei4gQi4ga2xlaW5lciBhbHMg4o26ID0KMCwwNSksIGRhbm4ga8O2bm5lbiB3aXIgbWl0IEhpbGZlIGVpbmVzIFBvc3QtSG9jLVRlc3RzIGhlcmF1c2ZpbmRlbiwKd2VsY2hlIEdydXBwZW4gYWJ3ZWljaGVuLgoKV2lyIHNlaGVuIGdsZWljaCBhbmhhbmQgdm9uIEJlaXNwaWVsZW4sIHdpZSBkaWUgQU5PVkEgZHVyY2hnZWbDvGhydCB3aXJkLAp3YXMgZGFzIGJlZGV1dGV0IHVuZCB3aWUgZGllc2UgenUgaW50ZXJwcmV0aWVyZW4gaXN0LgoKIyMjIFZvcmF1c3NldHp1bmdlbgoKQmV2b3IgZWluZSBBTk9WQSBkdXJjaGdlZsO8aHJ0IHdlcmRlbiBrYW5uLCBtdXNzIGdlcHLDvGZ0IHdlcmRlbiwgb2IgZGllCkRhdGVuIGRlbiBWb3JhdXNzZXR6dW5nZW4gZGVyIEFOT1ZBIGdlbsO8Z2VuLgoKRmFsbHMgZGllIERhdGVuIHp1IHNlaHIgdm9uIGRlbiBWb3JhdXNzZXR6dW5nZW4gYWJ3ZWljaGVuLCB2ZXJsaWVydCBkZXIKQU5PVkEtVGVzdCBhbiBBdXNzYWdla3JhZnQsIGQuIGguIGVzIGlzdCBmcmFnd8O8cmRpZy91bnNpY2hlciwgb2IgZGVtCkVyZ2VibmlzIHp1IHRyYXVlbiBpc3QuIERpZSBTdGF0aXN0aWsgc29sbCB1bnMgYWJzaWNoZXJuIChpbQpXYWhyc2NoZWlubGljaGtlaXRzc2lubiksIHdvIGVzIHN0YXRpc3Rpc2NoIHNpZ25pZmlrYW50ZSBVbnRlcnNjaGllZGUKZ2lidC4gRGFzIGlzdCBiZWkgZmVobGVuZGVyIEVyZsO8bGx1bmcgZGVyIFZvcmF1c3NldHp1bmdlbiBnZXN0w7ZydC5cCkVyaW5uZXJuIFNpZSBzaWNoIGFuIGRpZXNlciBTdGVsbGUgYXVjaCB6dXLDvGNrIGFuIGRpZSBCZWRldXR1bmcgZGVzCnAtV2VydHMuIERhcyBTaWduaWZpa2Fuem5pdmVhdSBnaWJ0IHN0ZXRzIGFuLCB3aWUgc2ljaGVyIHdpciBzaW5kIGJ6dy4Kc2VpbiB3b2xsZW4uCgpCZXRyYWNodGVuIHdpciB6dW7DpGNoc3QgZGllIFZvcmF1c3NldHp1bmdlbiBkZXIgQU5PVkEgdW5kIGJlZ2lubmVuIHdpcgptaXQgZWluZW0gRmFrdG9yLgoKIyMjIyBVbmFiaMOkbmdpZ2tlaXQgZGVyIEJlb2JhY2h0dW5nZW4KCkRpZSBCZW9iYWNodHVuZ2VuIG3DvHNzZW4gdW5hYmjDpG5naWcgdW5kIHp1ZsOkbGxpZyBzZWluLiBEYXMga2FubiBudXIgYmVpCmRlciBEdXJjaGbDvGhydW5nIGRlcyBFeHBlcmltZW50cyBnZXNjaGVoZW4sIGQuIGguIGRpZSBUZXN0b2JqZWt0ZSBkw7xyZmVuCmJlaXNwaWVsc3dlaXNlIG5pY2h0IHdpbGvDvHJsaWNoIG9kZXIgbWVocmZhY2ggZ2VtZXNzZW4gd2VyZGVuIChhdcOfZXIgYmVpCnplaXRsaWNoZW4gVmVybMOkdWZlbikgdW5kIHNvbGx0ZW4genVmw6RsbGlnICh6LiBCLiBkdXJjaApjb21wdXRlci1nZXN0w7x0enRlIHJhbmRvbWlzaWVydGUgWmFobGVuL0F1c3dhaGxlbikgYXVzZ2V3w6RobHQgd2VyZGVuLgoKIyMjIyBBdXNyZWnDn2VyCgpGw7xyIGRpZSDDvGJsaWNoZSBBTk9WQSBzb2xsdGVuIGtlaW5lIChleHRyZW1lbikgQXVzcmVpw59lciBpbiBkZW4gR3J1cHBlbgp2b3JsaWVnZW4uIERpZSBlaW5mYWNoc3RlIE3DtmdsaWNoa2VpdCB6dW0gRW50ZGVja2VuIHZvbiBBdXNyZWnDn2VybiBzaW5kCkJveHBsb3RzOgoKYGBge3J9CmdncGxvdChUb290aEdyb3d0aCkgKwogIGdlb21fYm94cGxvdChhZXMoc3VwcCwgbGVuLCBmaWxsID0gc3VwcCkpCmBgYAoKLSAgIFNpZSBzZWhlbiBvYmVyLXVuZCB1bnRlcmhhbGIgZGVyIFdoaXNrZXIga2VpbmUgQXVzcmVpw59lcgoKRmFsbHMgQXVzcmVpw59lciB2b3JoYW5kZW4gc2luZCwga8O2bm5lbiBkaWVzZSBtaXQgSGlsZmUgdm9uCmBpZGVudGlmeV9vdXRsaWVycygpYCBhdXMgYHJzdGF0aXhgIGVudGRlY2t0IHdlcmRlbjoKCmBgYHtyfQpUb290aEdyb3d0aCAlPiUKICBncm91cF9ieShzdXBwKSAlPiUKICBpZGVudGlmeV9vdXRsaWVycyhsZW4pCmBgYAoKLSAgIEF1c3JlacOfZXIgc2luZCBkZWZpbmllcnQgYWxzIGRpZWplbmlnZW4sIGRpZSBtZWhyIGFscyBkYXMgMSw1LWZhY2hlCiAgICB2b24gZGVtIDEuIGJ6dy4gMy4gUXVhcnRpbCBuYWNoIHVudGVuIGJ6dy4gb2JlbiBhYndlaWNoZW4uCgotICAgRXh0cmVtZSBBdXNyZWnDn2VyIHdlcmRlbiBiZWkgZGVyIGBpZGVudGlmeV9vdXRsaWVycygpYCBhbHMgZGllCiAgICAzLWZhY2hlIEFid2VpY2h1bmcgZGVmaW5pZXJ0LgoKRmFsbHMgZ3Jvw59lIEF1c3JlacOfZXIgdm9yaGFuZGVuIHNpbmQsIHNvbGx0ZSBnZXByw7xmdCB3ZXJkZW4sIG9iIGRpZXNlCk1lc3NmZWhsZXIgc2luZCB1bmQgb2IgZGllc2UgbWl0IGluIGRpZSBBbmFseXNlIGhpbmVpbmZsaWXDn2VuIHNvbGx0ZW4uCkFscyBBbHRlcm5hdGl2ZSB6dXIgQU5PVkEga8O2bm50ZSBkZXIgS3J1c2thbC1XYWxpcy1UZXN0IHJvYnVzdGVyIHNlaW4sCmZhbGxzIHZpZWxlL3N0YXJrZSBBdXNyZWnDn2VyIHZvcmhhbmRlbiBzaW5kLiBIaWVyZHVyY2ggd2lyZCBpbnNiZXNvbmRlcmUKbWVpc3RlbnMgZGllIE5vcm1hbHZlcnRlaWx1bmcgZ2VzdMO2cnQuCgojIyMjIE5vcm1hbHZlcnRlaWx1bmcKCkZhbGxzIGRpZSBBdXNyZWnDn2VyIHNpY2ggaW0gUmFobWVuIGhhbHRlbiwga8O2bm5lbiBkaWUgR3J1cHBlbiBhdWYKTm9ybWFsdmVydGVpbHVuZyBnZXRlc3RldCB3ZXJkZW4uCgpIaWVyenUga8O2bm5lbiBCb3hwbG90IHVuZCBIaXN0b2dyYW1tZSBuw7x0emxpY2ggc2VpbjoKCmBgYHtyfQpnZ3Bsb3QoVG9vdGhHcm93dGgsIGFlcyhsZW4sIGFmdGVyX3N0YXQoZGVuc2l0eSkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA0LCBmaWxsID0gInN0ZWVsYmx1ZSIpICsKICBnZW9tX2RlbnNpdHkoKSArCiAgZmFjZXRfd3JhcCh+c3VwcCkKYGBgCgotICAgQXVmIGRlbiBlcnN0ZW4gQmxpY2sgaXN0IGVzIHNjaHdlciB6dSBkZXV0ZW4sIG9iIGRpZSBEYXRlbgogICAgbm9ybWFsdmVydGVpbHQgc2luZC4KCi0gICBIaWVyenUgZsO8aHJlbiB3aXIgZGVuIFNoYXBpcm8tV2lsay1UZXN0IGbDvHIgamVkZSBHcnVwcGUgZHVyY2gsIHVtCiAgICB1bnMgYWJ6dXNpY2hlcm4uCgpgYGB7cn0KVG9vdGhHcm93dGggJT4lCiAgZ3JvdXBfYnkoc3VwcCkgJT4lCiAgc2hhcGlyb190ZXN0KGxlbikKYGBgCgotICAgRGVyIFRlc3Qgc3VnZ2VyaWVydCwgZGFzcyBiZWkgZWluZW0gU2lnbmlmaWthbnpuaXZlYXUgdm9uIDAsMDUgZGllCiAgICBMw6RuZ2UgYmV6w7xnbGljaCBkZXIgQXNrb3JiaW5zw6R1cmVncnVwcGUgbm9ybWFsdmVydGVpbHQgaXN0IChwIFw+IOKNuiwKICAgIEgwIHdpcmQgbmljaHQgYWJnZWxlaG50KSBqZWRvY2ggZGllIE9yYW5nZW5zYWZ0Z3J1cHBlIG5pY2h0CiAgICBub3JtYWx2ZXJ0ZWlsIGlzdCAocCBcPCDijbosIEgwIHdpcmQgYWJnZWxlaG50KS4KCkFubWVya3VuZzoKCi0gICBEaWUgQU5PVkEgaXN0IHR5cGlzY2hlcndlaXNlIHJlbGF0aXYgcm9idXN0IGdlZ2Vuw7xiZXIgZGVyIFZlcmxldHp1bmcKICAgIGRlciBWb3JhdXNzZXR6dW5nIGRlciBOb3JtYWx2ZXJ0ZWlsdW5nIGRlciBHcnVwcGVuLgoKLSAgIEZhbGxzIGRpZSBEYXRlbiBrZWluZXIgTm9ybWFsdmVydGVpbHVuZyBmb2xnZW4sIGthbm4gZWJlbmZhbGxzIGRlcgogICAgS3J1c2thbC1XYWxsaXMtVGVzdCBlaW5lIGd1dGUgQWx0ZXJuYXRpdmUgYmlldGVuLgoKLSAgIFRhdHPDpGNobGljaCBpc3QgZGllIE5vcm1hbHZlcnRlaWx1bmcgZGVyIFJlc2lkdWVuIGRlcyBsaW5lYXJlbgogICAgTW9kZWxscyB3aWNodGlnZXIuIERhcyB3b2xsZW4gd2lyIGhpZXIgYWJlciBuaWNodCBhdXNmw7xocmVuOgoKYGBge3J9Cm1vZGVsbCA8LSBsbShsZW4gfiBzdXBwLCBkYXRhID0gVG9vdGhHcm93dGgpCnNoYXBpcm9fdGVzdChyZXNpZHVhbHMobW9kZWxsKSkKYGBgCgojIyMjIFZhcmlhbnpob21vZ2VuaXTDpHQKClNjaGx1c3NlbmRsaWNoIHNvbGx0ZSBub2NoIGdlcHLDvGZ0IHdlcmRlbiwgb2IgZGllIFZhcmlhbnogYmV6w7xnbGljaCBkZXIKR3J1cHBlbiBob21vZ2VuIHNpbmQuCgpEYXMgbMOkc3N0IHNpY2ggYXVzIGRlbSBCb3hwbG90IGVudG5laG1lbiAoXH4gw6RobmxpY2ggaG9oZSBCb3hlbikgdW5kIG1pdApkZW0gTGV2ZW5lLVRlc3QgcHLDvGZlbjoKCmBgYHtyfQpUb290aEdyb3d0aCAlPiUKICBsZXZlbmVfdGVzdChsZW4gfiBzdXBwKQpgYGAKCkRpZSBIeXBvdGhlc2VuIGRlcyBMZXZlbmUtVGVzdHMgYmVzYWdlbjoKCi0gICBIMDogRGllIERhdGVuIHNpbmQgdmFyaWFuemhvbW9nZW4KCi0gICBIMTogRGllIERhdGVuIHNpbmQgbmljaHQgdmFyaWFuemhvbW9nZW4KCkRlbWVudHNwcmVjaGVuZCBsZWhuZW4gd2lyIGRpZSBOdWxsaHlwb3RoZXNlIEgwIG5pY2h0IGFiLCBkYSBkZXIgcC1XZXJ0Cmdyw7bDn2VyIGlzdCBhbHMgMCwwNS4gU29taXQgc2luZCBkaWUgR3J1cHBlbiAodmVybXV0bGljaCkgdmFyaWFuemhvbW9nZW4uCgojIyMgQU5PVkEKCkRhIGRpZSBEYXRlbiB2YXJpYW56aG9tb2dlbiBzaW5kIHVuZCBlcyBrZWluZSBBdXNyZWnDn2VyIGdpYnQsIGzDpHNzdCBzaWNoCmRpZSBBTk9WQSBhbndlbmRlbiwgYXVjaCB3ZW5uIGRpZSBEYXRlbiBuaWNodCBwZXJmZWt0IG5vcm1hbHZlcnRlaWx0CnNpbmQuIEluIGRlciBTdGFuZGFyZGJpYmxpb3RoZWsgdm9uIFIgZ2lidCBlcyBoaWVyZsO8ciBkaWUgYGFvdigpYApGdW5rdGlvbjoKCmBgYHtyfQplcmdlYm5pcyA8LSBhb3YobGVuIH4gc3VwcCwgZGF0YSA9IFRvb3RoR3Jvd3RoKQpzdW1tYXJ5KGVyZ2VibmlzKQpgYGAKCi0gICBgYW92KClgIGVyd2FydGV0IGFscyBFaW5nYWJlIGVpbmUgRm9ybWVsIG1pdCBkZXIgVGlsZGUgYH5gCgotICAgTGlua3Mgc3RlaHQgZGllIGFiaMOkbmdpZ2UgKGtvbnRpbnVpZXJsaWNoZSkgVmFyaWFibGUsIHJlY2h0cyBkaWUKICAgIGFiaMOkbmdpZ2VuIFZhcmlhYmxlbiAoRmFrdG9yZW4pCgotICAgRGFzIFNjaGVtYSBpc3QgZ2VuZXJlbGwgZ2xlaWNoIHdpZSBkaWUgRXJzdGVsbHVuZyBlaW5lcwogICAgUmVncmVzc2lvbnNtb2RlbGxzIG1pdCBgbG0oKWAKCk1pdCBIaWxmZSB2b24gYHN1bW1hcnkoKWAgc2VoZW4gd2lyIGRlbiBwLVdlcnQgZGVyIEFOT1ZBLCB3ZWxjaGVyIG1pdAowLDA2IGdyw7bDn2VyIGFscyBkYXMgdHlwaXNjaGUgU2lnbmlmaWthbnpuaXZlYXUgKDAsMDUpIGlzdC4KCkRlbW5hY2ggbmVobWVuIHdpciBhbiwgZGFzcyBlcyBrZWluZW4gc2lnbmlmaWthbnRlbiBVbnRlcnNjaGllZCBpbiBkZW4KWnVmdWhybWV0aG9kZW4gZ2lidC4KCkFsdGVybmF0aXYga8O2bm5lbiB3aXIgYXVjaCBhdXMgYHJzdGF0aXhgIGRpZSBGdW5rdGlvbiBgYW5vdmFfdGVzdCgpYAp2ZXJ3ZW5kZW46CgpgYGB7cn0KVG9vdGhHcm93dGggJT4lCiAgYW5vdmFfdGVzdChsZW4gfiBzdXBwKQpgYGAKClRlc3RlbiB3aXIgZWJlbmZhbGxzIGRpZSBEb3NpcyAoYGRvc2VgKSB2b24gVml0YW1pbiBDIGF1ZiBkZW4gRWluZmx1c3MKZGVzIFphaG53YWNoc3R1bXMuIE5laG1lbiB3aXIgYW4sIGRhc3MgZGllIEFOT1ZBIFZvcmF1c3NldHp1bmdlbiBlcmbDvGxsdAp3dXJkZW46CgpgYGB7cn0KYW92X2VyZ2VibmlzIDwtIFRvb3RoR3Jvd3RoICU+JQogIGFub3ZhX3Rlc3QobGVuIH4gZG9zZSkKYW92X2VyZ2VibmlzCmBgYAoKLSAgIERlciBwLVdlcnQgaXN0IHNlaHIga2xlaW4sIGQuIGguIG1pbmRlc3RlbnMgZWluZSBHcnVwcGUKICAgIHVudGVyc2NoZWlkZXQgc2ljaCBzaWduaWZpa2FudCB2b24gZGVuIGFuZGVyZW4uCgotICAgV2VsY2hlIEdydXBwZSBkYXMgaXN0LCBsw6Rzc3Qgc2ljaCBhbmhhbmQgZWluZXMgUG9zdC1Ib2MtVGVzdHMKICAgIGZlc3RzdGVsbGVuLgoKIyMjIFBvc3QtSG9jLVRlc3QKCkJlaSBkZW0gUG9zdC1Ib2MtVGVzdCBzb2xsIGZlc3RnZXN0ZWxsdCB3ZXJkZW4sIHdlbGNoZSBHcnVwcGVuIHNpY2gKc2lnbmlmaWthbnQgdW50ZXJzY2hlaWRlbiwgZGEgZGllIEFOT1ZBIG51ciBzdWdnZXJpZXJ0LCBvYiBzaWNoIGVpbmUKR3J1cHBlIHVudGVyc2NoZWlkZXQuCgpEYSBoaWVyYmVpIGplZGVzIEdydXBwZW5wYWFyIHNlcGFyYXQgZ2V0ZXN0ZXQgd2lyZCwgbcO8c3NlbiBkaWUgcC1XZXJ0ZQphbmdlcGFzc3Qgd2VyZGVuIChgcC5hZGpgKSwgZGEgc29uc3QgZGllIFdhaHJzY2hlaW5saWNoa2VpdCBzdGVpZ3QsIGRhc3MKc2ljaCBkZXIgVGVzdCBpcnJ0IChkdXJjaCBtZWhyZmFjaGVzIFRlc3RlbikuCgpEZXIgYmVsaWVidGVzdGUgUG9zdC1Ib2MtVGVzdCBkZXIgZWluZmFjaGVuIEFOT1ZBIGlzdCBkZXIKVHVrZXktSFNELVRlc3QuIEbDvHIgZGllIGBhb3YoKWAgRXJnZWJuaXNzZSB3aXJkIGRpZXNlciB3aWUgZm9sZ3QKZHVyY2hnZWbDvGhydDoKCmBgYHtyfQplcmdlYm5pcyA8LSBhb3YobGVuIH4gZG9zZSwgZGF0YSA9IFRvb3RoR3Jvd3RoKQpUdWtleUhTRChlcmdlYm5pcykKYGBgCgotICAgRGllIFVudGVyc2NoaWVkZSBzaW5kIGbDvHIgYWxsZSBHcnVwcGVuIHNpZ25pZmlrYW50LCBkYSBkaWUgcC1XZXJ0ZQogICAgc2VociBrbGVpbiBzaW5kLgoKLSAgIERlbW5hY2gga2FubiBkYXZvbiBhdXNnZWdhbmdlbiB3ZXJkZW4sIGRhc3MgZGllIE1lbmdlIGFuIFZpdGFtaW4gQwogICAgZWluZW4gc2lnbmlmaWthbnRlbiBFaW5mbHVzcyBhdWYgZGFzIFdhY2hzdHVtIGRlciBaw6RobmUgZGVyCiAgICBNZWVyc2Nod2VpbmNoZW4gaGF0LgoKQWx0ZXJuYXRpdiBrw7ZubmVuIHdpciBkYXMgZWJlbmZhbGxzIG1pdCBgcnN0YXRpeGAgZHVyY2hmw7xocmVuLiBEZXIKVm9ydGVpbCBpc3QgaGllcmJlaSwgZGFzcyBzaWNoIGRpZSBUYWJlbGxlIG1pdCBkZW4gcC1XZXJ0ZW4gZGlyZWt0CnNwZWljaGVybiBsw6Rzc3Q6CgpgYGB7cn0KdHVrZXkgPC0gVG9vdGhHcm93dGggJT4lCiAgdHVrZXlfaHNkKGxlbiB+IGRvc2UpCnR1a2V5CiMgRXJnZWJuaXMgYWxzIFRhYmVsbGUgc3BlaWNoZXJuOgojIHdyaXRlX2Nzdih0dWtleSwgInR1a2V5X2VyZ2VibmlzLmNzdiIpCmBgYAoKRGFzIEVyZ2VibmlzIGvDtm5uZW4gU2llIG51biBiZWlzcGllbHN3ZWlzZSBiZWxpZWJpZyBrw7xyemVuLCB1bSBudXIgZGllCnJlbGV2YW50ZSBJbmZvcm1hdGlvbiAoc2lnbmlmaWthbnQsIG5pY2h0IHNpZ25pZmlrYW50KSB6dSBleHRyYWhpZXJlbjoKCmBgYHtyfQojIEdydXBwZW52ZXJnbGVpY2gKdHVrZXlfZG9zZSA8LSB0dWtleSAlPiUKCWRwbHlyOjpzZWxlY3QoZ3JvdXAxLCBncm91cDIsIHAuYWRqKQp0dWtleV9kb3NlCiMgQWxzIE1hdHJpeDoKdHVrZXlfZG9zZSAlPiUKCXBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBncm91cDEsIHZhbHVlc19mcm9tID0gcC5hZGopCmBgYAoKRGFzIEVyZ2VibmlzIGzDpHNzdCBzaWNoIGF1Y2ggYW5oYW5kIGVpbmVzIEJveHBsb3RzIG5hY2h2b2xsemllaGJhcgpkYXJzdGVsbGVuOgoKYGBge3J9CiMgU2V0emUgZGllIFBvc2l0aW9uIGRlciBLbGFtbWVybjoKdHVrZXkgPC0gdHVrZXkgJT4lCiAgYWRkX3h5X3Bvc2l0aW9uKHggPSAiZG9zZSIpCiMgWmVpY2huZSBCb3hwbG90cyBmw7xyIHNpZ25pZmlrYW50ZSBHcnVwcGVuOgpnZ3Bsb3QoVG9vdGhHcm93dGgpICsKICBnZW9tX2JveHBsb3QoYWVzKGRvc2UsIGxlbiwgZmlsbCA9IGRvc2UpKSArCiAgZ2dwdWJyOjpzdGF0X3B2YWx1ZV9tYW51YWwodHVrZXksIGhpZGUubnMgPSBUUlVFKSArICMgZsO8Z3QgcC1XZXJ0ZSBoaW56dQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IE5VTEwpICsKICAjIFp1c8OkdHpsaWNoZSBJbmZvcm1hdGlvbiBkZXMgVGVzdHM6CiAgbGFicyh0aXRsZSA9ICJWaXRhbWluIEMgZsO2cmRlcnQgWmFobndhY2hzdHVtIGJlaSBNZWVyc2Nod2VpbmNoZW4iLAogICAgICAgc3VidGl0bGUgPSBnZXRfdGVzdF9sYWJlbChhb3ZfZXJnZWJuaXMsIGRldGFpbGVkID0gVFJVRSksCiAgICAgICBjYXB0aW9uID0gZ2V0X3B3Y19sYWJlbCh0dWtleSksCiAgICAgICB4ID0gIlZpdGFtaW4gQyBEb3NpcyAobWcvVGFnKSIsCiAgICAgICB5ID0gIlphaG5sw6RuZ2UgKEzDpG5nZSBkZXIgT2RvbnRvYmxhc3RlbikiLAogIAkJIGZpbGwgPSAiRG9zaXMiKQpgYGAKCiMjIyBNZWhyZXJlIEZha3RvcmVuCgpadXZvciBoYWJlbiB3aXIgbGVkaWdsaWNoIGVpbmVuIEZha3RvcmVuIGJldHJhY2h0ZXQuIEluIGRlciBSZWFsaXTDpHQKc29sbGVuIG1laXN0IG1laHJlcmUgRmFrdG9yZW4genVnbGVpY2ggZ2V0ZXN0ZXQgd2VyZGVuICh6LiBCLiBWaXRhbWluIEMKRG9zaXMgdW5kIFp1ZnVocmFydCkuIEluIGRpZXNlbSBGYWxsIGJpZXRldCBzaWNoIGVpbmUgbWVocmZha3RvcmllbGxlCkFOT1ZBIGFuLgoKRGllc2UgZnVua3Rpb25pZXJ0IHdpcmQgcHJpbnppcGllbGwgc2VociDDpGhubGljaCB6dXIgZWluZmFrdG9yaWVsbGVuCkFOT1ZBIGR1cmNoZ2Vmw7xocnQuCgpCZXRyYWNodGVuIHdpciBlcm5ldXQgZGVuIGBUb290aEdyb3d0aGAgRGF0ZW5zYXR6IHVuZCBwcsO8ZmVuIGRpZQpWb3JhdXNzZXR6dW5nZW4gbnVuIGbDvHIgendlaSBGYWt0b3Jlbi4KCiMjIyMgQXVzcmVpw59lcgoKYGBge3J9CmdncGxvdChUb290aEdyb3d0aCkgKwogIGdlb21fYm94cGxvdChhZXMoc3VwcCwgbGVuLCBmaWxsID0gZG9zZSwgY29sb3IgPSBsZW4pKQpUb290aEdyb3d0aCAlPiUKICBncm91cF9ieShzdXBwLCBkb3NlKSAlPiUKICBpZGVudGlmeV9vdXRsaWVycyhsZW4pCmBgYAoKLSAgIEVzIGxpZWdlbiB6d2VpIEF1c3JlacOfZXIgdm9yLiBEYXMgbWFnIG5vY2ggaW0gUmFobWVuIGxpZWdlbgoKIyMjIyBOb3JtYWx2ZXJ0ZWlsdW5nCgpgYGB7cn0KVG9vdGhHcm93dGggJT4lCiAgZ3JvdXBfYnkoc3VwcCwgZG9zZSkgJT4lCiAgc2hhcGlyb190ZXN0KGxlbikKYGBgCgotICAgRGllIHAtV2VydGUgc2luZCBhbGxlIGdyw7bDn2VyIGFscyBkYXMgw7xibGljaGUgU2lnbmlmaWthbnpuaXZlYXUsCiAgICBzb2Rhc3MgYWxsZSBHcnVwcGVuIG5vcm1hbHZlcnRlaWx0IHNpbmQuCgojIyMjIFZhcmlhbnpob21vZ2VuaXTDpHQKCmBgYHtyfQpUb290aEdyb3d0aCAlPiUKICBsZXZlbmVfdGVzdChsZW4gfiBzdXBwICogZG9zZSkKYGBgCgotICAgRXMgaXN0IHdpY2h0aWcsIGhpZXJiZWkgZGFzIGAqYC1TeW1ib2wgenUgdmVyd2VuZGVuLCBkYW1pdCBlYmVuZmFsbHMKICAgIGRpZSBJbnRlcmFrdGlvbiBnZXRlc3RldCB3aXJkLgotICAgRGEgZGVyIHAtV2VydCDDvGJlciBkZW0gw7xibGljaGVuIFNpZ25pZmlrYW56bml2ZWF1IGxpZWd0LCBuZWhtZW4gd2lyCiAgICBkaWUgVmFyaWFuemhvbW9nZW5pdMOkdCBhbi4KCiMjIyMgWndlaWZha3RvcmllbGxlIEFOT1ZBCgpEYSBhbGxlIFZvcmF1c3NldHp1bmdlbiBlcmbDvGxsdCBzaW5kLCBrYW5uIGRpZSB6d2VpZmFrdG9yaWVsbGUgQU5PVkEKZHVyY2hnZWbDvGhydCB3ZXJkZW46CgpgYGB7cn0KendlaV9mYWt0b3JfYW92IDwtIFRvb3RoR3Jvd3RoICU+JQogIGFub3ZhX3Rlc3QobGVuIH4gc3VwcCAqIGRvc2UpCnp3ZWlfZmFrdG9yX2FvdgpgYGAKCi0gICBCZWFjaHRlbiBTaWUsIGRhc3MgYmVpIGRpZXNlbSBNb2RlbGwgZGFzIGAqYCBmw7xyIGRpZSBCZXRyYWNodHVuZyBkZXIKICAgIGVpbnplbG5lbiB1bmFiaMOkbmdpZ2VuIFZhcmlhYmxlbiBhbHMgSGF1cHRlZmZla3Qgc293aWUgZGVzc2VuCiAgICBJbnRlcmFrdGlvbiBzdGVodC4KCi0gICBEYXMgYCtgIFN5bWJvbCBiZXRyYWNodGV0IG51ciBkaWUgdW5hYmjDpG5naWdlbiBWYXJpYWJsZW4gb2huZSBkZXNzZW4KICAgIEludGVyYWt0aW9uLgoKLSAgIERhcyBgOmAgU3ltYm9sIGJldHJhY2h0ZXQgbnVyIGRpZSBJbnRlcmFrdGlvbiBkZXIgdW5hYmjDpG5naWdlbgogICAgVmFyaWFibGVuIG9obmUgZGVuIEhhdXB0ZWZmZWt0LgoKLSAgIFNpZSBzZWhlbiwgZGFzcyBhbGxlIEVmZmVrdGUgKEhhdXB0ZWZmZWt0ZSBzb3dpZSBJbnRlcmFrdGlvbikKICAgIHNpZ25pZmlrYW50IHNpbmQsIGQuIGguIGVzIGdpYnQgaW5uZXJoYWxiIGRlciBlaW56ZWxuZW4gR3J1cHBlbgogICAgc2lnbmlmaWthbnRlIFVudGVyc2NoaWVkZSBzb3dpZSBiZWkgZGVyIGdlbWVpbnNhbWVuIEJldHJhY2h0dW5nIGRlcgogICAgR3J1cHBlbiAoSW50ZXJha3Rpb24pLgoKIyMjIyBQb3N0LUhvYy1UZXN0CgpEYSBkaWUgSW50ZXJha3Rpb24gc2lnbmlmaWthbnQgaXN0LCBrw7ZubmVuIHdpciBkZW4gRWZmZWt0IHZvbiBgZG9zZWAgZsO8cgpqZWRlIFN0dWZlIHZvbiBgc3VwcGAgaW4gZWluZXIgZWluZmFrdG9yaWVsbGVuIEFOT1ZBIGJldHJhY2h0ZW46CgpgYGB7cn0KVG9vdGhHcm93dGggJT4lCiAgZ3JvdXBfYnkoc3VwcCkgJT4lCiAgYW5vdmFfdGVzdChsZW4gfiBkb3NlKQpgYGAKCi0gICBXaXIgc2VoZW4sIGRhc3MgZGVyIEhhdXB0ZWZmZWt0IHZvbiBkZXIgRG9zaXMgYXVmIGRpZSBaYWhubMOkbmdlCiAgICBzaWduaWZpa2FudCB3YXIgZsO8ciBiZWlkZSBadWZ1aHJhcnRlbi4KCk51biB3b2xsZW4gd2lyIHdpc3Nlbiwgd2VsY2hlIGRlciBHcnVwcGVuIHNpY2ggdW50ZXJzY2hlaWRlbjoKCmBgYHtyfQpUb290aEdyb3d0aCAlPiUKICBncm91cF9ieShzdXBwKSAlPiUKICB0dWtleV9oc2QobGVuIH4gZG9zZSkKYGBgCgotICAgV2lyIHNlaGVuLCBkYXNzIHNpY2ggYWxsZSBHcnVwcGVuIHNpZ25pZmlrYW50IHVudGVyc2NoZWlkZW4gKGJ6Z2wuCiAgICBkZXIgWmFobmxhbmdlKSBhdcOfZXIgZGVyIFZlcmdsZWljaCB2b24gT3JhbmdlbnNhZnQgYmVpIGRlciBFaW5uYWhtZQogICAgdm9uIDFtZyB6dSAybWcgVml0YW1pbiBDIGFtIFRhZy4KCi0gICBXZW5uIHdpcmtsaWNoIGplZGUgR3J1cHBlIG1pdGVpbmFuZGVyIHZlcmdsaWNoZW4gd2VyZGVuIHNvbGwsIGthbm4KICAgIGRhcyBlYmVuZmFsbHMgbWl0IGRlbSBUdWtleS1IU0QtVGVzdCBkdXJjaGdlZsO8aHJ0IHdlcmRlbi4gSGllcmJlaQogICAgc2luZCBkaWUgcC1XZXJ0ZSBhbGxlcmRpbmdzIGV0d2FzIGdyw7bDn2VyLCBkYSBkaWVzZSBkdXJjaCBkaWUgaMO2aGVyZQogICAgVGVzdGFuemFobCB3ZWl0ZXIga29ycmlnaWVydCB3ZXJkZW4gKGBwLmFkamApOgoKYGBge3J9ClRvb3RoR3Jvd3RoICU+JQogIHR1a2V5X2hzZChsZW4gfiBzdXBwICogZG9zZSkKYGBgCgpXw6RyZSBkaWUgSW50ZXJha3Rpb24gbmljaHQgc2lnbmlmaWthbnQsIGvDtm5udGUgZGVubm9jaCBtaXQgcGFhcndlaXNlbgpUZXN0cyAoei4gQi4gcGFhcndlaXNlbiB0LVRlc3RzIGBwYWlyd2lzZV90X3Rlc3QoKWAsIFR1a2V5KSBuYWNoClVudGVyc2NoaWVkZW4gaW4gZGVuIEhhdXB0ZWZmZWt0ZW4gZ2VzY2hhdXQgd2VyZGVuIG9obmUgZGllIEludGVyYWt0aW9uCihmYWxscyBlaW4gSGF1cHRlZmZla3Qgc2lnbmlmaWthbnQgaXN0KS4KCkRhcyBlbnRzcHJpY2h0IGRlbSwgd2FzIHdpciBiZWkgZGVyIGVpbmZha3RvcmllbGxlbiBBTk9WQSBiZXJlaXRzCmR1cmNoZ2Vmw7xocnQgaGFiZW4uCgpGYWxscyBtYW4gZGFyYW4gaW50ZXJlc3NpZXJ0IGlzdCwgdmVyc2NoaWVkZW5lIEdydXBwZW5hdWZ0ZWlsdW5nZW4KbWl0ZWluYW5kZXIgenUgdmVyZ2xlaWNoZW4gKHouIEIuIERvc2lzIDAuNS8xbWcvVGFnIGdlZ2VuIERvc2lzCjJtZy9UYWcpLCBkYW5uIGJpZXRldCBzaWNoIHp1bSBCZWlzcGllbCBkaWUgYGdsaHRgIEZ1bmt0aW9uIGF1cwpgbXVsdGNvbXBgIGFuLiBTaWVoZSBoaWVyenUKW2hpZXJdKGh0dHBzOi8vcmRyci5pby9jcmFuL211bHRjb21wL21hbi9nbGh0Lmh0bWwpLgoKIyMgQWx0ZXJuYXRpdmUgVGVzdHMgenVyIChlaW5mYWt0b3JpZWxsZW4pIEFOT1ZBCgpBbiBkaWVzZXIgU3RlbGxlIGVpbmUgRW50c2NoZWlkdW5nc2hpbGZlLCB3ZWxjaGVyIFRlc3QgYmVpIGRlcgplaW5mYWt0b3JpZWxsZW4gQW5hbHlzZSB2ZXJ3ZW5kZXQgd2VyZGVuIHNvbGx0ZToKCiFbRW50c2NoZWlkdW5nc2JhdW0gQU5PVkFdKGltYWdlcy9kZWNpc2lvbl90cmVlLTAxLmpwZykKCiMjIyBXZWxjaAoKV2VubiBkaWUgQmVkaW5ndW5nIGRlciBWYXJpYW56aG9tb2dlbml0w6R0IGRlciBHcnVwcGVuIGJlaSBkZXIKZWluZmFrdG9yaWVsbGVuIEFOT1ZBIG5pY2h0IGVpbmdlaGFsdGVuIGlzdCwga2FubiBkZXIgV2VsY2gtVGVzdCBhbHMKcm9idXN0ZXJlIEFOT1ZBLVZhcmlhbnRlIHZlcndlbmRldCB3ZXJkZW4uIERpZSBlaW5mYWNoZSBBTk9WQSB2ZXJsaWVydApzZWhyIHZpZWwgQXVzc2FnZWtyYWZ0LCB3ZW5uIGRpZSBEYXRlbiBuaWNodCB2YXJpYW56aG9tb2dlbiBzaW4uCgpEZXIgV2VsY2gtVGVzdCB3aXJkIGFuYWxvZyBkdXJjaGdlZsO8aHJ0IHVuZCBtZWlzdGVucyBtaXQgZGVuClBvc3QtSG9jLVRlc3RzIHZvbiBHYW1lcy1Ib3dlbGwgb2RlciBkZW0gcGFhcndlaXNlbiB0LVRlc3Qga29tYmluaWVydCwKZGEgZGllc2UgYmVpIFZhcmlhbnppbmhvbW9nZW5pdMOkdCByb2J1c3RlciBzaW5kOgoKYGBge3J9CndlbGNoX2VyZ2VibmlzIDwtIFRvb3RoR3Jvd3RoICU+JQogIHdlbGNoX2Fub3ZhX3Rlc3QobGVuIH4gZG9zZSkKd2VsY2hfZXJnZWJuaXMKYGBgCgpEaWUgbcO2Z2xpY2hlbiBQb3N0LUhvYy1UZXN0cyBsYXNzZW4gc2ljaCBlYmVuc28gYW5hbG9nIHdpZSB6dXZvcgp2ZXJ3ZW5kZW46CgpgYGB7cn0KIyBHYW1lcy1Ib3dlbGw6CmdhbWVzX2hvd2VsbF9lcmdlYm5pcyA8LSBUb290aEdyb3d0aCAlPiUKICBnYW1lc19ob3dlbGxfdGVzdChsZW4gfiBkb3NlKQpnYW1lc19ob3dlbGxfZXJnZWJuaXMKIyB0LVRlc3RzOiBWb3JzaWNodDogZGVyIFBhcmFtZXRlciBwb29sLnNkID0gRkFMU0UgaXN0IHdpY2h0aWcsCiMgZGFtaXQga2VpbmUgVmFyaWFuemhvbW9nZW5pdMOkdCB2b3JhdXNnZXNldHp0IGlzdApwYWFyd190X3Rlc3RfZXJnZWJuaXMgPC0gVG9vdGhHcm93dGggJT4lCiAgcGFpcndpc2VfdF90ZXN0KGxlbiB+IGRvc2UsIHBvb2wuc2QgPSBGQUxTRSkKcGFhcndfdF90ZXN0X2VyZ2VibmlzCmBgYAoKLSAgIERpZSBwLVdlcnRlIHVudGVyc2NoZWlkZW4gc2ljaCBsZWljaHQsIGdlYmVuIGFiZXIgZGllc2VsYmUgVGVuZGVuegogICAgYW4uCgojIyMgS3J1c2thbC1XYWxsaXMKCkZhbGxzIGRpZSBWb3JhdXNzZXR6dW5nZW4gZGVyIGVpbmZha3RvcmllbGxlbiBBTk9WQSBnw6RuemxpY2ggbmljaHQKZ2VnZWJlbiBzaW5kIChiencuIGRpZSBEYXRlbiBuaWNodCBhbm7DpGhlcm5kIG5vcm1hbHZlcnRlaWx0KSwga2FubiBkZXIKbmljaHQtcGFyYW1ldHJpc2NoZSBLcnVza2FsLVdhbGxpcy1UZXN0IGR1cmNoZ2Vmw7xocnQgd2VyZGVuLiBBbHMKUG9zdC1Ib2MtVGVzdCB3aXJkIG5hY2ggZGVtIEtydXNrYWwtV2FsbGlzLVRlc3QgZW50d2VkZXIgZGVyCldpbGNveG9uLVRlc3Qgb2RlciBkZXIgRHVubi1UZXN0IGR1cmNoZ2Vmw7xocnQ6CgpgYGB7cn0KIyBLcnVza2FsLVdhbGxpcy1UZXN0OgpUb290aEdyb3d0aCAlPiUKICBrcnVza2FsX3Rlc3QobGVuIH4gZG9zZSkKIyBEdW5uLVRlc3Q6ClRvb3RoR3Jvd3RoICU+JQogIGR1bm5fdGVzdChsZW4gfiBkb3NlKQojIFdpbGNveG9uLVRlc3Q6ClRvb3RoR3Jvd3RoICU+JQogIHdpbGNveF90ZXN0KGxlbiB+IGRvc2UpCmBgYAoKLSAgIERpZSBJbnRlcnByZXRhdGlvbiBkZXIgVGVzdGVyZ2Vibmlzc2UgZm9sZ3QgZGVyIGVpbmZhY2hlbiBBTk9WQS4KCiMjIyBNZWhyZmFrdG9yZW4KCkZhbGxzIGRpZSBWb3JhdXNzZXR6dW5nZW4gZGVyIERhdGVuIGRlciB6d2VpZmFrdG9yaWVsbGVuIEFOT1ZBIG5pY2h0CmdlbsO8Z2VuLCBnaWJ0IGVzIG1laHJlcmUgTcO2Z2xpY2hrZWl0ZW4uCgotICAgRXMgZ2lidCBrZWluZW4gYWx0ZXJuYXRpdmVuIG5pY2h0LXBhcmFtZXRyaXNjaGVuIFRlc3QgZsO8ciBtZWhyZXJlCiAgICBGYWt0b3JlbiwgZGVyIGViZW5mYWxscyBkaWUgSW50ZXJha3Rpb24gZGllc2VyIGJldHJhY2h0ZW4ga2Fubi4KCi0gICBTb2Zlcm4gZGllIE5vcm1hbHZlcnRlaWx1bmcgbmljaHQgZ2VnZWJlbiBpc3QsIGthbm4gZGllCiAgICB6d2VpZmFrdG9yaWVsbGUgQU5PVkEgbWVpc3QgZGVubm9jaCB2ZXJ3ZW5kZXQgd2VyZGVuLCB3b2JlaSBkaWUKICAgIEVyZ2Vibmlzc2UgZ2dmLiB1bnRlciBWb3JiZWhhbHQgenUgaW50ZXJwcmV0aWVyZW4gc2luZC4KCi0gICBGYWxscyBkaWUgSW50ZXJha3Rpb24gZWluZSB1bnRlcmdlb3JkbmV0ZSBSb2xsZSBzcGllbHQsIGxpZcOfZSBzaWNoCiAgICBhdWNoIGbDvHIgamVkZW4gRmFrdG9yIGVpbmUgZWluZmFrdG9yaWVsbGUgQU5PVkEgZHVyY2hmw7xocmVuLCB1bQogICAgaW5uZXJoYWxiIGRlciBlaW56ZWxuZW4gR3J1cHBlbiBVbnRlcnNjaGllZGUgenUgZmluZGVuLgoKLSAgIEZhbGxzIGVzIHZpZWxlIEF1c3JlacOfZXIgZ2lidCBvZGVyIGRpZSBWYXJpYW56aG9tb2dlbml0w6R0IG5pY2h0CiAgICBnZWdlYmVuIGlzdCwgYmlldGV0IGVzIHNpY2ggYW4sIEtvcnJla3R1cm1ldGhvZGVuIHp1IHZlcndlbmRlbiB1bmQKICAgIGRpZSBEYXRlbiB6dSB0cmFuc2Zvcm1pZXJlbiAoei4gQi4gbG9nLVRyYW5zZm9ybWF0aW9uLAogICAgQm94LUNveC1UcmFuc29mbXJhdGlvbiksIHNvZGFzcyBkaWVzZSB2YXJpYW56aG9tb2dlbiAodW5kCiAgICBub3JtYWx2ZXJ0ZWlsdCkgc2luZC5cCiAgICBGw7xyIGVpbmUgdHlwaXNjaGUgS29ycmVrdHVybWV0aG9kZSBzaWVoZSBiZWlzcGllbHN3ZWlzZQogICAgW2hpZXJdKGh0dHBzOi8vd3d3LnN0YXRvbG9neS5vcmcvYm94LWNveC10cmFuc2Zvcm1hdGlvbi1pbi1yLykuCgotICAgQWx0ZXJuYXRpdiBrYW5uIGF1Y2ggZWluIFtyb2J1c3RlcwogICAgUmVncmVzc2lvbnNtb2RlbGxdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JvYnVzdF9yZWdyZXNzaW9uKQogICAgZXJzdGVsbHQgd2VyZGVuLgoKIyMgQW5kZXJlIEFOT1ZBLVRlc3RzCgpOZWJlbiBkZXIgZWluZmFjaGVuIEFOT1ZBIGdpYnQgZXMgbm9jaCB3ZWl0ZXJlIEFydGVuIGRlciBBTk9WQSwgZGllIGbDvHIKc3BlemlmaXNjaGUgQW53ZW5kdW5nc2bDpGxsZSBhdXNnZWxlZ3Qgc2luZC4KCiMjIyBXaWVkZXJob2x0ZSBNZXNzdW5nZW4KCldlbm4gZGllc2VsYmVuIFVudGVyc3VjaHVuZ3NvYmpla3RlIHp1IG1laHJlcmVuIFplaXRwdW5rdGVuIGdlbWVzc2VuCnd1cmRlbiwgd2lyZCBlaW5lIHNwZXppZWxsZSBBTk9WQSBmw7xyIHdpZWRlcmhvbHRlIE1lc3N1bmdlbiB2ZXJ3ZW5kZXQuCkRhcyBgcnN0YXRpeGAgUGFrZXQgYmlldGV0IG1pdCBgYW5vdmFfdGVzdCgpYCBlYmVuZmFsbHMgRnVua3Rpb25hbGl0w6R0CmbDvHIgZGllIEFOT1ZBIGbDvHIgW3dpZWRlcmhvbHRlCk1lc3N1bmdlbl0oaHR0cHM6Ly93d3cuZGF0YW5vdmlhLmNvbS9lbi9sZXNzb25zL3JlcGVhdGVkLW1lYXN1cmVzLWFub3ZhLWluLXIvKS4KCiMjIyBNaXhlZCBBTk9WQQoKV2VubiBkaWVzZWxiZW4gVW50ZXJzdWNodW5nc29iamVrdGUgenUgbWVocmVyZW4gWmVpdHB1bmt0ZW4gZ2VtZXNzZW4Kd3VyZGVuIHVuZCB6dXPDpHR6bGljaCBlaW4gd2VpdGVyZXIgRmFrdG9yIGJldHJhY2h0ZXQgd2VyZGVuIHNvbGwsIHdpcmQKZWluZSBnZW1pc2NodGUgQU5PVkEgdmVyd2VuZGV0LiBBdWNoIGRpZXNlIEZ1bmt0aW9uYWxpdMOkdCBiaWV0ZXQKYGFub3ZhX3Rlc3QoKWAgZsO8ciBbZ2VtaXNjaHRlIEFOT1ZBCkRlc2lnbnNdKGh0dHBzOi8vd3d3LmRhdGFub3ZpYS5jb20vZW4vbGVzc29ucy9taXhlZC1hbm92YS1pbi1yLykuCgojIyMgQU5DT1ZBCgpXZW5uIGVpbmUgZWluZmFjaGUgQU5PVkEgZHVyY2hnZWbDvGhydCB3ZXJkZW4gc29sbCwgamVkb2NoIHp1c8OkdHpsaWNoIGbDvHIKZWluZSBrb250aW51aWVybGljaGUgVmFyaWFibGUgKEtvdmFyaWF0ZSkgZGllIEFOT1ZBIGtvcnJpZ2llcnQgd2VyZGVuCnNvbGwsIHdpcmQgZGllIEFOQ09WQSB2ZXJ3ZW5kZXQuIEbDvHIgbWVociBJbmZvcm1hdGlvbiB6dXIgQU5DT1ZBIHNpZWhlCltoaWVyXShodHRwczovL3d3dy5kYXRhbm92aWEuY29tL2VuL2xlc3NvbnMvYW5jb3ZhLWluLXIvKS4KCiMjIyBNQU5PVkEKCkFsbGUgdm9yaGVyaWdlbiBBTk9WQSBWZXJmYWhyZW4gaGF0dGVuIGdlbWVpbnNhbSwgZGFzcyBudXIgZWluZQprb250aW51aWVybGljaGUgVmFyaWFibGUgYWxzIGFiaMOkbmdpZ2UgVmFyaWFibGUgYmV0cmFjaHRldCB3dXJkZS4KCkZhbGxzIGdsZWljaHplaXRpZyBtZWhyZXJlIGtvbnRpbnVpZXJsaWNoZSBWYXJpYWJsZSBpbiBlaW5lciBBTk9WQSBhbHMKWmllbHZhcmlhYmxlIGJldHJhY2h0ZXQgd2VyZGVuIHNvbGxlbiwga2FubiBlaW5lIE1BTk9WQSAobXVsdGl2YXJpYXRlCkFOT1ZBKSB2ZXJ3ZW5kZXQgd2VyZGVuIGFuc3RlbGxlIGRlciBEdXJjaGbDvGhydW5nIHZvbiBtZWhyZXJlbiBlaW5mYWNoZW4KQU5PVkFzLgoKRsO8ciBtZWhyIEluZm9ybWF0aW9uIHp1ciBNQU5PVkEgc2llaGUKW2hpZXJdKGh0dHBzOi8vd3d3LmRhdGFub3ZpYS5jb20vZW4vbGVzc29ucy9vbmUtd2F5LW1hbm92YS1pbi1yLykuCgpCZWRlbmtlbiBTaWUsIGRhc3MgZXMgaW4gUiBtZWlzdGVucyBtZWhyZXJlIE3DtmdsaWNoa2VpdGVuIHVuZCBQYWtldGUKZ2lidCwgZGllc2VsYmVuIEFuYWx5c2VuIGR1cmNoenVmw7xocmVuLgoKRmFsbHMgU2llIHNwZXppZWxsZSBUZXN0cy9WZXJmYWhyZW4gdmVyd2VuZGVuIHdvbGxlbiwgc29sbHRlbiBTaWUgc3RldHMKZWluZSBTdWNobWFzY2hpbmUgYXVmc3VjaGVuIHVuZCBuYWNoIGVpbmVtIHBhc3NlbmRlbiBleHRlcm5lbiBQYWtldApzdWNoZW4uIEbDvHIgc3RhdGlzdGlzY2hlIFRlc3RzIHNpbmQgYmVpc3BpZWxzd2Vpc2UgYGNhcmAsIGBNQVNTYCBvZGVyCmBtdWx0Y29tcGAgcHJvbWluZW50ZSBQYWtldGUuCgpCZWRlbmtlbiBTaWUgYXVjaCwgZGFzcyBqZWRlciBzdGF0aXN0aXNjaGUgVGVzdCB2ZXJzY2hpZWRlbmUKVm9yYXVzc2V0enVuZ2VuIGhhdCB1bmQgd8OkaGxlbiBTaWUgc28gZGVuIHBhc3NlbmRlbiBUZXN0IGF1cy4gQXVjaCBkaWUKdmVyc2NoaWVkZW5lbiBBTk9WQS1WZXJmYWhyZW4gaGFiZW4gdmVyc2NoaWVkZW5lIFZvcmF1c3NldHp1bmdlbi4KCiMgQXVmZ2FiZW4KCkluIGRpZXNlbSBUZWlsIHdvbGxlbiB3aXIgZGVuIERhdGVuc2F0eiBgbnBrYCBhdXN3ZXJ0ZW46CgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCm5wayA8LSBhc190aWJibGUobnBrKQpucGsKYGBgCgpXaWUgYmVyZWl0cyBlcmzDpHV0ZXJ0IGhhbmRlbHQgZXMgc2ljaCBiZWkgZGVtIERhdGVuc2F0eiB1bSBlaW4gdHlwaXNjaGVuCnZvbGxzdMOkbmRpZ2VuIFZlcnN1Y2hzcGxhbiBhdXMgZGVtIEJlcmVpY2ggZGVyIEFncmFyd2lzc2Vuc2NoYWZ0ZW4uIERlcgpEYXR6ZW5zYXR6IGJlc2NocmVpYnQgZGVuIEVpbmZsdXNzIGRlcyBFaW5zYXR6ZXMgdm9uIFN0aWNrc3RvZmYgKGBOYCksClBob3NwaGF0IChgUGApIHVuZCBLYWxpdW0gKGBLYCkgYXVmIGRlbiBFcnRyYWcgdm9uIEVyYnNlbiAoYHlpZWxkYCkuCgojIyDDnGJ1bmdzYXVmZ2FiZW4KCjEuICBXZXJ0ZW4gU2llIGRlbiBEYXR6ZW5zYXR6IGBucGtgIG1pdCBlaW5lciBwYXNzZW5kZW4gQU5PVkEgYXVzLgoKICAgIDEuICBWZXJzY2hhZmZlbiBTaWUgc2ljaCBlaW5lICh2aXN1ZWxsZS9zdGF0aXN0aXNjaGUpIMOcYmVyc2ljaHQgw7xiZXIKICAgICAgICBkaWUgRGF0ZW4uCgogICAgMi4gIFByw7xmZW4gU2llIGRpZSBWb3JhdXNzZXR6dW5nZW4gZGVyIGVpbmZhY2hlbiBBTk9WQS4KCiAgICAzLiAgV2VuZGVuIFNpZSBkYXMgcGFzc2VuZGUgQU5PVkEtTW9kZWxsIGFuLgoKICAgIDQuICBJbnRlcnByZXRpZXJlbiBTaWUgZGllIEVyZ2Vibmlzc2UuCg==