Install appropriate packages and open the libraries.
library(Hmisc)
library(funModeling)
library(tidyverse)
Source, Target, and Weight Data Frame
The data represent a summary of a Telegram network that consists of
eight channels, namely “cyber_frontZ,” “ruserbia,” “orly_rs,”
“balkan_spy,” “russkeydomserbia,” “Prigozhin_hat,” “rtbalkan_ru,” and
“narodnapatrola.”
The “source” column identifies the channel, while the
“unique_domains” and “total_URLs” columns represent the number of
distinct domains and URLs shared in each channel, respectively.
stats <- data.frame(ch_stats)
datatable(stats)
The data suggests that the cyber_frontZ channel is the most active in
terms of sharing, with the highest number of unique domains (1610) and
total URLs (9106) shared. In contrast, the narodnapatrola and
russkeydomserbia channels had the lowest number of unique domains and
total URLs shared, with only 25 and 77 unique domains and 194 and 196
total URLs, respectively.
The total number of unique domains and total URLs shared across all
channels is 2095 and 17339, respectively. This means that the
cyber_frontZ channel alone is responsible for sharing the majority of
the URLs and unique domains within the network.
Summary Statistics for Core Channels
Looking at the summary statistics, we can see that the mean number of
unique domains (378.2) and total URLs (2211.1) in the Telegram network
are much higher than the minimum values (25 and 194, respectively). The
25 and 194 are the minimum values across all channels, while the means
represent the average values across all channels. This suggests that
there is a wide range of unique domains and URLs being shared across the
network.
The median number of unique domains (87) and total URLs (857) across
all channels are lower than the means, indicating that the distribution
of the data may be positively skewed. This is also supported by the
positive skewness values for both variables reported in the additional
information.
The interquartile ranges (IQR) for unique domains (390.75) and total
URLs (2544.75) are relatively large, which further supports the notion
of variability in the data. The maximum values for both variables are
quite large, with 1610 unique domains and 9106 total URLs, indicating
that some channels are particularly active in sharing URLs and unique
domains.
Overall, the additional information provides context for the summary
statistics previously given, allowing for a more comprehensive
understanding of the distribution of unique domains and URLs in the
Telegram network.
Basic Exploratory Data Analysis
Basic EDA (Exploratory Data Analysis) is an initial and informal
examination of data to understand its main characteristics. It is often
the first step in a data analysis process and can help identify
potential problems or interesting patterns in the data.
Basic EDA typically involves looking at the distribution of the
variables in the dataset, checking for missing values or outliers,
identifying patterns or relationships between variables, and summarizing
key statistics such as means, medians, and standard deviations.
Convert data to data frame.
Plot function.
plot_function <- function(df) {
# insert code to create a plot of the data
# for example, using ggplot2:
ggplot(data = df) +
geom_histogram(aes(x = "total_URLs"), bins = 10)
}
plot_function
function(df) {
# insert code to create a plot of the data
# for example, using ggplot2:
ggplot(data = df) +
geom_histogram(aes(x = "total_URLs"), bins = 10)
}
Glimpse function.
glimpse_function <- function(df) {
# insert code to print a summary of the data structure and variable types
# for example, using dplyr:
glimpse(df)
}
glimpse_function(df)
Rows: 8
Columns: 3
$ source <chr> "cyber_frontZ", "ruserbia", "orly_rs", "rtbalkan_ru", "balkan_spy", "…
$ unique_domains <dbl> 1610, 745, 354, 55, 97, 63, 25, 77
$ total_URLs <dbl> 9106, 3904, 2366, 1269, 445, 209, 196, 194
Summary function.
summary_function <- function(df)
{
# insert code to print a summary of the data values
# for example, using base R:
summary(df)
}
summary_function(df)
source unique_domains total_URLs
Length:8 Min. : 25.0 Min. : 194.0
Class :character 1st Qu.: 61.0 1st Qu.: 205.8
Mode :character Median : 87.0 Median : 857.0
Mean : 378.2 Mean :2211.1
3rd Qu.: 451.8 3rd Qu.:2750.5
Max. :1610.0 Max. :9106.0
Profiling function.
profiling_num_function <- function(df) {
# insert code to create a numeric variable profiling report
# for example, using dplyr and tidyr:
stats %>%
select_if(is.numeric) %>%
gather(key = "variable", value = "value") %>%
group_by(variable) %>%
summarize(mean = mean(value, na.rm = TRUE),
sd = sd(value, na.rm = TRUE),
min = min(value, na.rm = TRUE),
max = max(value, na.rm = TRUE),
median = median(value, na.rm = TRUE),
n_missing = sum(is.na(value)))
}
profiling_num_function(df)
Plot the Core Channel Data
The code uses the ggplot2 package to create two histograms of the
“unique_domains” and “total_URLs” variables contained in the
“ch_stats.csv”, now “df”, data.
For the first histogram, the code specifies that the x-axis will show
the “unique_domains” variable, and that the y-axis will show the
frequency of occurrence of that variable. The code then specifies that
the plot should be created using the “geom_histogram” function, which
will create a histogram of the data. Finally, the “labs” function is
used to add x and y axis labels to the plot.
For the second histogram, the code is similar, except that it
specifies that the x-axis should show the “total_URLs” variable, and
that the plot should be labeled accordingly.
Overall, the code creates two histograms of the data contained in the
“df” data frame, providing a visual representation of the distribution
of unique domains and total URLs shared in the Telegram network.
ggplot(df, aes(x = unique_domains)) + geom_histogram() + labs(x = "Unique Domains", y = "Frequency")

ggplot(df, aes(x = total_URLs)) + geom_histogram() + labs(x = "Total URLs", y = "Frequency")

Describe Core Channels
Grouping and Percentages for Edges
df <- data.frame(ch_stats)
profiling_num_function(df)
The “describe(df)” code is used to provide a summary of the
distribution of values for each column in the df data frame.
Write file to save results.
print(profiling_num(df))
write.csv(profiling_num(df), file = "prof_num_ch_stats.csv")
Combined
df <- data.frame(stats)
basic_eda <- function(stats) {
plot(stats)
plot_num(stats)
glimpse(stats)
summary(stats)
profiling_num(stats)
}
basic_eda(stats)
Rows: 8
Columns: 3
$ source <chr> "cyber_frontZ", "ruserbia", "orly_rs", "rtbalkan_ru", "balkan_spy", "…
$ unique_domains <dbl> 1610, 745, 354, 55, 97, 63, 25, 77
$ total_URLs <dbl> 9106, 3904, 2366, 1269, 445, 209, 196, 194


LS0tDQp0aXRsZTogIkJyb3RoZXJseSBJbmZvcm1hdGlvbiBPcGVyYXRpb25zIg0Kc3VidGl0bGU6ICJSLUNvZGUgZm9yIGNoX3N0YXRzLmNzdiINCmF1dGhvcjogIkhvYXhsaW5lcyINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQotLS0NCg0KXA0KXA0KSW5zdGFsbCBhcHByb3ByaWF0ZSBwYWNrYWdlcyBhbmQgb3BlbiB0aGUgbGlicmFyaWVzLg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQogICAgbGlicmFyeShIbWlzYykNCiAgICBsaWJyYXJ5KGZ1bk1vZGVsaW5nKSANCiAgICBsaWJyYXJ5KHRpZHl2ZXJzZSkgDQoNCmBgYHtyfQ0KbGlicmFyeShIbWlzYykNCmxpYnJhcnkoZnVuTW9kZWxpbmcpIA0KbGlicmFyeSh0aWR5dmVyc2UpIA0KYGBgDQoNClwNClwNCg0KIyMjIFNvdXJjZSwgVGFyZ2V0LCBhbmQgV2VpZ2h0IERhdGEgRnJhbWUNClRoZSBkYXRhIHJlcHJlc2VudCBhIHN1bW1hcnkgb2YgYSBUZWxlZ3JhbSBuZXR3b3JrIHRoYXQgY29uc2lzdHMgb2YgZWlnaHQgY2hhbm5lbHMsIG5hbWVseSAiY3liZXJfZnJvbnRaLCIgInJ1c2VyYmlhLCIgIm9ybHlfcnMsIiAiYmFsa2FuX3NweSwiICJydXNza2V5ZG9tc2VyYmlhLCIgIlByaWdvemhpbl9oYXQsIiAicnRiYWxrYW5fcnUsIiBhbmQgIm5hcm9kbmFwYXRyb2xhLiINCg0KVGhlICJzb3VyY2UiIGNvbHVtbiBpZGVudGlmaWVzIHRoZSBjaGFubmVsLCB3aGlsZSB0aGUgInVuaXF1ZV9kb21haW5zIiBhbmQgInRvdGFsX1VSTHMiIGNvbHVtbnMgcmVwcmVzZW50IHRoZSBudW1iZXIgb2YgZGlzdGluY3QgZG9tYWlucyBhbmQgVVJMcyBzaGFyZWQgaW4gZWFjaCBjaGFubmVsLCByZXNwZWN0aXZlbHkuDQoNCmBgYHtyfQ0Kc3RhdHMgPC0gZGF0YS5mcmFtZShjaF9zdGF0cykNCmRhdGF0YWJsZShzdGF0cykNCmBgYA0KDQpUaGUgZGF0YSBzdWdnZXN0cyB0aGF0IHRoZSBjeWJlcl9mcm9udFogY2hhbm5lbCBpcyB0aGUgbW9zdCBhY3RpdmUgaW4gdGVybXMgb2Ygc2hhcmluZywgd2l0aCB0aGUgaGlnaGVzdCBudW1iZXIgb2YgdW5pcXVlIGRvbWFpbnMgKDE2MTApIGFuZCB0b3RhbCBVUkxzICg5MTA2KSBzaGFyZWQuDQpJbiBjb250cmFzdCwgdGhlIG5hcm9kbmFwYXRyb2xhIGFuZCBydXNza2V5ZG9tc2VyYmlhIGNoYW5uZWxzIGhhZCB0aGUgbG93ZXN0IG51bWJlciBvZiB1bmlxdWUgZG9tYWlucyBhbmQgdG90YWwgVVJMcyBzaGFyZWQsIHdpdGggb25seSAyNSBhbmQgNzcgdW5pcXVlIGRvbWFpbnMgYW5kIDE5NCBhbmQgMTk2IHRvdGFsIFVSTHMsIHJlc3BlY3RpdmVseS4NCg0KVGhlIHRvdGFsIG51bWJlciBvZiB1bmlxdWUgZG9tYWlucyBhbmQgdG90YWwgVVJMcyBzaGFyZWQgYWNyb3NzIGFsbCBjaGFubmVscyBpcyAyMDk1IGFuZCAxNzMzOSwgcmVzcGVjdGl2ZWx5Lg0KVGhpcyBtZWFucyB0aGF0IHRoZSBjeWJlcl9mcm9udFogY2hhbm5lbCBhbG9uZSBpcyByZXNwb25zaWJsZSBmb3Igc2hhcmluZyB0aGUgbWFqb3JpdHkgb2YgdGhlIFVSTHMgYW5kIHVuaXF1ZSBkb21haW5zIHdpdGhpbiB0aGUgbmV0d29yay4NCg0KXA0KXA0KDQojIyMgU3VtbWFyeSBTdGF0aXN0aWNzIGZvciBDb3JlIENoYW5uZWxzDQpgYGB7ciBlY2hvPUZBTFNFfQ0Kc3VtbWFyeShzdGF0cykNCmBgYA0KDQpMb29raW5nIGF0IHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MsIHdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBudW1iZXIgb2YgdW5pcXVlIGRvbWFpbnMgKDM3OC4yKSBhbmQgdG90YWwgVVJMcyAoMjIxMS4xKSBpbiB0aGUgVGVsZWdyYW0gbmV0d29yayBhcmUgbXVjaCBoaWdoZXIgdGhhbiB0aGUgbWluaW11bSB2YWx1ZXMgKDI1IGFuZCAxOTQsIHJlc3BlY3RpdmVseSkuDQpUaGUgMjUgYW5kIDE5NCBhcmUgdGhlIG1pbmltdW0gdmFsdWVzIGFjcm9zcyBhbGwgY2hhbm5lbHMsIHdoaWxlIHRoZSBtZWFucyByZXByZXNlbnQgdGhlIGF2ZXJhZ2UgdmFsdWVzIGFjcm9zcyBhbGwgY2hhbm5lbHMuDQpUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlcmUgaXMgYSB3aWRlIHJhbmdlIG9mIHVuaXF1ZSBkb21haW5zIGFuZCBVUkxzIGJlaW5nIHNoYXJlZCBhY3Jvc3MgdGhlIG5ldHdvcmsuDQoNClRoZSBtZWRpYW4gbnVtYmVyIG9mIHVuaXF1ZSBkb21haW5zICg4NykgYW5kIHRvdGFsIFVSTHMgKDg1NykgYWNyb3NzIGFsbCBjaGFubmVscyBhcmUgbG93ZXIgdGhhbiB0aGUgbWVhbnMsIGluZGljYXRpbmcgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBkYXRhIG1heSBiZSBwb3NpdGl2ZWx5IHNrZXdlZC4NClRoaXMgaXMgYWxzbyBzdXBwb3J0ZWQgYnkgdGhlIHBvc2l0aXZlIHNrZXduZXNzIHZhbHVlcyBmb3IgYm90aCB2YXJpYWJsZXMgcmVwb3J0ZWQgaW4gdGhlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24uDQoNClRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlcyAoSVFSKSBmb3IgdW5pcXVlIGRvbWFpbnMgKDM5MC43NSkgYW5kIHRvdGFsIFVSTHMgKDI1NDQuNzUpIGFyZSByZWxhdGl2ZWx5IGxhcmdlLCB3aGljaCBmdXJ0aGVyIHN1cHBvcnRzIHRoZSBub3Rpb24gb2YgdmFyaWFiaWxpdHkgaW4gdGhlIGRhdGEuIFRoZSBtYXhpbXVtIHZhbHVlcyBmb3IgYm90aCB2YXJpYWJsZXMgYXJlIHF1aXRlIGxhcmdlLCB3aXRoIDE2MTAgdW5pcXVlIGRvbWFpbnMgYW5kIDkxMDYgdG90YWwgVVJMcywgaW5kaWNhdGluZyB0aGF0IHNvbWUgY2hhbm5lbHMgYXJlIHBhcnRpY3VsYXJseSBhY3RpdmUgaW4gc2hhcmluZyBVUkxzIGFuZCB1bmlxdWUgZG9tYWlucy4NCg0KT3ZlcmFsbCwgdGhlIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gcHJvdmlkZXMgY29udGV4dCBmb3IgdGhlIHN1bW1hcnkgc3RhdGlzdGljcyBwcmV2aW91c2x5IGdpdmVuLCBhbGxvd2luZyBmb3IgYSBtb3JlIGNvbXByZWhlbnNpdmUgdW5kZXJzdGFuZGluZyBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIHVuaXF1ZSBkb21haW5zIGFuZCBVUkxzIGluIHRoZSBUZWxlZ3JhbSBuZXR3b3JrLg0KDQpcDQpcDQoNCiMjIyBCYXNpYyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzDQpCYXNpYyBFREEgKEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMpIGlzIGFuIGluaXRpYWwgYW5kIGluZm9ybWFsIGV4YW1pbmF0aW9uIG9mIGRhdGEgdG8gdW5kZXJzdGFuZCBpdHMgbWFpbiBjaGFyYWN0ZXJpc3RpY3MuDQpJdCBpcyBvZnRlbiB0aGUgZmlyc3Qgc3RlcCBpbiBhIGRhdGEgYW5hbHlzaXMgcHJvY2VzcyBhbmQgY2FuIGhlbHAgaWRlbnRpZnkgcG90ZW50aWFsIHByb2JsZW1zIG9yIGludGVyZXN0aW5nIHBhdHRlcm5zIGluIHRoZSBkYXRhLg0KDQpCYXNpYyBFREEgdHlwaWNhbGx5IGludm9sdmVzIGxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgdmFyaWFibGVzIGluIHRoZSBkYXRhc2V0LCBjaGVja2luZyBmb3IgbWlzc2luZyB2YWx1ZXMgb3Igb3V0bGllcnMsIGlkZW50aWZ5aW5nIHBhdHRlcm5zIG9yIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMsIGFuZCBzdW1tYXJpemluZyBrZXkgc3RhdGlzdGljcyBzdWNoIGFzIG1lYW5zLCBtZWRpYW5zLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucy4NCg0KQ29udmVydCBkYXRhIHRvIGRhdGEgZnJhbWUuDQpgYGB7cn0NCmRmIDwtIGRhdGEuZnJhbWUoc3RhdHMpDQpkZg0KYGBgDQoNClwNCg0KUGxvdCBmdW5jdGlvbi4NCmBgYHtyIGVjaG89VFJVRX0NCnBsb3RfZnVuY3Rpb24gPC0gZnVuY3Rpb24oZGYpIHsNCiAgIyBpbnNlcnQgY29kZSB0byBjcmVhdGUgYSBwbG90IG9mIHRoZSBkYXRhDQogICMgZm9yIGV4YW1wbGUsIHVzaW5nIGdncGxvdDI6DQogIGdncGxvdChkYXRhID0gZGYpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9ICJ0b3RhbF9VUkxzIiksIGJpbnMgPSAxMCkNCn0NCnBsb3RfZnVuY3Rpb24NCmBgYA0KDQpcDQoNCkdsaW1wc2UgZnVuY3Rpb24uDQpgYGB7cn0NCmdsaW1wc2VfZnVuY3Rpb24gPC0gZnVuY3Rpb24oZGYpIHsNCiAgIyBpbnNlcnQgY29kZSB0byBwcmludCBhIHN1bW1hcnkgb2YgdGhlIGRhdGEgc3RydWN0dXJlIGFuZCB2YXJpYWJsZSB0eXBlcw0KICAjIGZvciBleGFtcGxlLCB1c2luZyBkcGx5cjoNCiAgZ2xpbXBzZShkZikNCn0NCmdsaW1wc2VfZnVuY3Rpb24oZGYpDQpgYGANCg0KXA0KDQpTdW1tYXJ5IGZ1bmN0aW9uLg0KYGBge3J9DQpzdW1tYXJ5X2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKGRmKSANCnsNCiAgIyBpbnNlcnQgY29kZSB0byBwcmludCBhIHN1bW1hcnkgb2YgdGhlIGRhdGEgdmFsdWVzDQogICMgZm9yIGV4YW1wbGUsIHVzaW5nIGJhc2UgUjoNCiAgc3VtbWFyeShkZikNCn0NCnN1bW1hcnlfZnVuY3Rpb24oZGYpDQpgYGANCg0KXA0KDQpQcm9maWxpbmcgZnVuY3Rpb24uDQpgYGB7cn0NCnByb2ZpbGluZ19udW1fZnVuY3Rpb24gPC0gZnVuY3Rpb24oZGYpIHsNCiAgIyBpbnNlcnQgY29kZSB0byBjcmVhdGUgYSBudW1lcmljIHZhcmlhYmxlIHByb2ZpbGluZyByZXBvcnQNCiAgIyBmb3IgZXhhbXBsZSwgdXNpbmcgZHBseXIgYW5kIHRpZHlyOg0KICBzdGF0cyAlPiUNCiAgICBzZWxlY3RfaWYoaXMubnVtZXJpYykgJT4lDQogICAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbHVlIikgJT4lDQogICAgZ3JvdXBfYnkodmFyaWFibGUpICU+JQ0KICAgIHN1bW1hcml6ZShtZWFuID0gbWVhbih2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgc2QgPSBzZCh2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgbWluID0gbWluKHZhbHVlLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICBtYXggPSBtYXgodmFsdWUsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgIG1lZGlhbiA9IG1lZGlhbih2YWx1ZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgbl9taXNzaW5nID0gc3VtKGlzLm5hKHZhbHVlKSkpIA0KfQ0KcHJvZmlsaW5nX251bV9mdW5jdGlvbihkZikNCmBgYA0KDQoNCiMjIyBQbG90IHRoZSBDb3JlIENoYW5uZWwgRGF0YQ0KVGhlIGNvZGUgdXNlcyB0aGUgZ2dwbG90MiBwYWNrYWdlIHRvIGNyZWF0ZSB0d28gaGlzdG9ncmFtcyBvZiB0aGUgInVuaXF1ZV9kb21haW5zIiBhbmQgInRvdGFsX1VSTHMiIHZhcmlhYmxlcyBjb250YWluZWQgaW4gdGhlICJjaF9zdGF0cy5jc3YiLCBub3cgImRmIiwgZGF0YS4NCg0KRm9yIHRoZSBmaXJzdCBoaXN0b2dyYW0sIHRoZSBjb2RlIHNwZWNpZmllcyB0aGF0IHRoZSB4LWF4aXMgd2lsbCBzaG93IHRoZSAidW5pcXVlX2RvbWFpbnMiIHZhcmlhYmxlLCBhbmQgdGhhdCB0aGUgeS1heGlzIHdpbGwgc2hvdyB0aGUgZnJlcXVlbmN5IG9mIG9jY3VycmVuY2Ugb2YgdGhhdCB2YXJpYWJsZS4NClRoZSBjb2RlIHRoZW4gc3BlY2lmaWVzIHRoYXQgdGhlIHBsb3Qgc2hvdWxkIGJlIGNyZWF0ZWQgdXNpbmcgdGhlICJnZW9tX2hpc3RvZ3JhbSIgZnVuY3Rpb24sIHdoaWNoIHdpbGwgY3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBkYXRhLg0KRmluYWxseSwgdGhlICJsYWJzIiBmdW5jdGlvbiBpcyB1c2VkIHRvIGFkZCB4IGFuZCB5IGF4aXMgbGFiZWxzIHRvIHRoZSBwbG90Lg0KDQpGb3IgdGhlIHNlY29uZCBoaXN0b2dyYW0sIHRoZSBjb2RlIGlzIHNpbWlsYXIsIGV4Y2VwdCB0aGF0IGl0IHNwZWNpZmllcyB0aGF0IHRoZSB4LWF4aXMgc2hvdWxkIHNob3cgdGhlICJ0b3RhbF9VUkxzIiB2YXJpYWJsZSwgYW5kIHRoYXQgdGhlIHBsb3Qgc2hvdWxkIGJlIGxhYmVsZWQgYWNjb3JkaW5nbHkuDQoNCk92ZXJhbGwsIHRoZSBjb2RlIGNyZWF0ZXMgdHdvIGhpc3RvZ3JhbXMgb2YgdGhlIGRhdGEgY29udGFpbmVkIGluIHRoZSAiZGYiIGRhdGEgZnJhbWUsIHByb3ZpZGluZyBhIHZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIHVuaXF1ZSBkb21haW5zIGFuZCB0b3RhbCBVUkxzIHNoYXJlZCBpbiB0aGUgVGVsZWdyYW0gbmV0d29yay4NCg0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyh4ID0gdW5pcXVlX2RvbWFpbnMpKSArIGdlb21faGlzdG9ncmFtKCkgKyBsYWJzKHggPSAiVW5pcXVlIERvbWFpbnMiLCB5ID0gIkZyZXF1ZW5jeSIpDQpnZ3Bsb3QoZGYsIGFlcyh4ID0gdG90YWxfVVJMcykpICsgZ2VvbV9oaXN0b2dyYW0oKSArIGxhYnMoeCA9ICJUb3RhbCBVUkxzIiwgeSA9ICJGcmVxdWVuY3kiKQ0KYGBgDQoNClwNClwNCg0KIyMjIERlc2NyaWJlIENvcmUgQ2hhbm5lbHMNCkdyb3VwaW5nIGFuZCBQZXJjZW50YWdlcyBmb3IgRWRnZXMNCmBgYHtyfQ0KZGYgPC0gZGF0YS5mcmFtZShjaF9zdGF0cykNCnByb2ZpbGluZ19udW1fZnVuY3Rpb24oZGYpDQpgYGANCg0KYGBge3J9DQpwcm9maWxpbmdfbnVtX2Z1bmN0aW9uKGRmKQ0KcGxvdChkZikNCmBgYA0KDQpcDQpcDQoNClRoZSAiZGVzY3JpYmUoZGYpIiBjb2RlIGlzIHVzZWQgdG8gcHJvdmlkZSBhIHN1bW1hcnkgb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgZm9yIGVhY2ggY29sdW1uIGluIHRoZSBkZiBkYXRhIGZyYW1lLg0KYGBge3J9DQpkZXNjcmliZShkZikNCmBgYA0KDQpcDQoNClwNCg0KV3JpdGUgZmlsZSB0byBzYXZlIHJlc3VsdHMuDQoNCmBgYHtyfQ0KcHJpbnQocHJvZmlsaW5nX251bShkZikpDQp3cml0ZS5jc3YocHJvZmlsaW5nX251bShkZiksIGZpbGUgPSAicHJvZl9udW1fY2hfc3RhdHMuY3N2IikNCmBgYA0KDQpcDQpcDQoNCiMjIyBDb21iaW5lZA0KYGBge3J9DQpkZiA8LSBkYXRhLmZyYW1lKHN0YXRzKQ0KYmFzaWNfZWRhIDwtIGZ1bmN0aW9uKHN0YXRzKSB7DQogIHBsb3Qoc3RhdHMpDQogIHBsb3RfbnVtKHN0YXRzKQ0KICBnbGltcHNlKHN0YXRzKQ0KICBzdW1tYXJ5KHN0YXRzKQ0KICBwcm9maWxpbmdfbnVtKHN0YXRzKQ0KfQ0KDQpiYXNpY19lZGEoc3RhdHMpDQpgYGANCg==