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