Основною метою дослідження було визначити в межах Кривого Рогу загальну площу території, яку покрито “живою” (не засохлою) рослинністю. При цьому особливим завданням було виокремити території, які покриті деревною рослинністю. Для цього упродовж декількох днів я візуально вивчав фактичні дані про стан газонів, скверів, пустирів та інших об’єктів у Кривому Розі. Під час візуального обстеження стало зрозумілим, що лише мала частка власне газонів представлена “живою” травою. Більшість спостережених мною ділянок несли або вельми пригнічену, або взагалі висохлу трав’яну рослинність. Також стало зрозумілим, що в окремий клас території треба винести пустирі та очерети. Пустирі здебільшого вкриті або багаторічними високорослими травами (деревій, полин, амброзія тощо), або сумішшю низькорослих та високорослих трав. Також майже всюди на пустирях трапляються поодинокі дерева. Очерети займають особливе місце у міській рослинності, оскільки вони вказують на близьке знаходження ґрунтових вод (зони підтоплення). Також очерети, зростаючи на берегах та у водоймах, вказують на ступінь замулення поверхневих водойм.
Через малу кількість “живих” газонів довелось трохи змістити рівень детектування класу “газон”. Під час класифікації до “газонів” мною було віднесено не лише власне “газони”, а й будь-які ділянки з низькорослими “живими” травами - доглянуті стадіони, частини пустирів, ділянки суходолу в безпосередній близькості до водних об’єктів.
Загалом в рамках дослідження було виділено 9 умовних класів:
“Очерети” (Bulrush) — суцільні зарості очеретів;
“Випалена територія” (Burned Area) — ділянки вигорілої внаслідок пожеж рослинності. Цей клас окремо виділено через те, що протягом нетривалого часу вигоріли ділянки заростають травами та переходять до класу “газон” або “пустир”;
“Ліс” (Forest) — щільні лісові насадження із кущами та травами;
“Газон” (Lawn) — ділянки низькотрав’я з нормальною (“живою”) рослинністю;
“Парк” (Park) — ділянки з нещільними насадженнями дерев. В якості еталону цього класу взято міські парки та сквери;
“Тверда поверхня” (Solid) — будь-які тверді поверхні: дороги, бетон, оголені ґрунти, скельні породи, антропогенні об’єкти (кар’єри, відвали, хвостосховища тощо). Тобто до цього класу увійшли всі типи територій, які не покриті рослинністю та водою;
“Приватний сектор” (Village) — вибір цього класу обумовлений специфічністю одноповерхової міської забудови: щільна суміш дерев, трав, твердих поверхонь, побудов та споруд. Така суміш різнородних об’єктів у межах одного пікселю космічного знімку призводить до специфічного відбиття як оптичних так і радарних хвиль;
“Пустир” (Wasteland) — ділянки із сумішшю низькорослих та високорослих трав і поодиноких дерев. Здебільшого — це недоглянуті земельні ділянки, які схильні до самозаростання рослинністю;
“Вода” (Water) — будь-які відкриті водні поверхні (ріки, ставки, відстійники, хвостосховища тощо)
В якості первинних матеріалів взято:
знімок космічного апарату Sentinel-1A від 7 серпня 2017 року (GRD) в поляризаціях VH та VV;
канали 2, 3, 4, 5, 6, 7, 8, 8A, 11 та 12 знімку космічного апарату Sentinel-2A від 8 серпня 2017 року;
канали 10 та 11 космічного апарату Landsat-8 від 12 серпня 2017 року;
канал 8 знімку космічного апарату Sentinel-2A від 30 квітня 2017 року.
Для радарного знімку було проведено радіометричну корекцію, фільтрацію спекл-шуму (з використанням фільтру Gamma Map), обчислення сили відбиття в децибелах та геометричну корекцію (Range-Doppler). Для цього було використано програмний засіб SNAP (Sentinels Application Platform).
Знімки оптичних супутників оброблено з використанням модулю Semi-Automatic Classification Plugin геоінформаційної системи QGIS (Sentinel-2A) та SAGA GIS (Landsat-8).
Після підготовчого оброблення всі знімки було завантажено в геоінформаційну систему SAGA. Там виконано поканальне об’єднання двох гранул знімків космічного апарату Sentinel-2A (TWT та UWU), обрізання всіх знімків по контуру Кривого Рогу (контур взято з проекту OpenStreetMap), приведення всіх знімків до розміру пікселю 10Х10 м. При цьому в якості “основи” використовувався знімок космічного апарату Sentinel-2A.
Для формування навчальної вибірки об’єктів зроблено сегментацію досліджуваної території базовим методом Object Based Image Segmentation геоінформаційної системи SAGA. Потім незначній частині полігонів отриманого шейп-шару приписано означені вище класи території. Загалом було прокласифіковано 1070 полігонів. Кількість полігонів за класами значно різниться.
Наступні кроки виконувались в середовищі мови програмування R. Нижче містяться скрипти, якими виконувався весь процес обчислення та перевірки даних.
#Завантажуємо потрібні пакети
library(plyr)#саме в такій послідовності: спочатку plyr, потім dplyr!
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:plyr’:
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
The following objects are masked from ‘package:raster’:
intersect, select, union
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(raster)
library(ggplot2)
#Встановлюємо директорію для кешування "великих растрів"
rasterOptions(tmpdir = "/home/geka/ssd/LargeTMP/")
#Завантажуємо у вигляді окремих об'єктів всі супутникові матеріали
Image_S2B2 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B02_KrR.sdat")
Image_S2B3 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B03_KrR.sdat")
Image_S2B4 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B04_KrR.sdat")
Image_S2B5 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B05_KrR.sdat")
Image_S2B6 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B06_KrR.sdat")
Image_S2B7 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B07_KrR.sdat")
Image_S2B8 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B08_KrR.sdat")
Image_S2B8A <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B8A_KrR.sdat")
Image_S2B11 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B11_KrR.sdat")
Image_S2B12 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170808_B12_KrR.sdat")
Image_L8B10 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/RT_LC08_L1TP_178027_20170812_20170812_01_RT_B10_KrR.sdat")
Image_L8B11 <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/RT_LC08_L1TP_178027_20170812_20170812_01_RT_B11_KrR.sdat")
Image_S1VH <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S1A_GRDH_20170807_SigmaVH_db_KrR.sdat")
Image_S1VV <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S1A_GRDH_20170807_SigmaVV_db_KrR.sdat")
Image_S2B8APR <- raster("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/S2_TWT_UWU_20170430_B08_KrR.sdat")
#Об'єднуємо всі канали в один об'єкт
ImageStack <- stack(Image_S2B2, Image_S2B3, Image_S2B4, Image_S2B5, Image_S2B6,
Image_S2B7, Image_S2B8, Image_S2B8A, Image_S2B11, Image_S2B12,
Image_L8B10, Image_L8B11, Image_S1VH, Image_S1VV, Image_S2B8APR)
#Перейменовуємо канали в об'єднаному об'єкті
names(ImageStack) <- c("S2B2", "S2B3", "S2B4", "S2B5", "S2B6", "S2B7",
"S2B8", "S2B8A", "S2B11", "S2B12",
"L8B10", "L8B11", "S1VH", "S1VV", "S2B8APR")
#Візуально перевіряємо адекватність та повноту даних
plotRGB(ImageStack, r = 7, g = 11, b = 14, stretch = "hist")

#Завантажуємо шейп-файл з навчальними полігонами
trainShape <- shapefile("/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/Segments_Class_noDegLawn.shp")
#Відкидаємо "порожні" полігони - ті, яким не присвоювалось жодних класів
trainData <- trainShape[!is.na(trainShape@data$Class) ,]
#Робимо поле цілих чисел з номерами класів
trainData@data$ClassInt <- as.integer(factor(trainData@data$Class))
#Перевіряємо кількість наявних учбових полігонів за класами
summary(factor(trainData@data$Class))
Bulrush Burned Area Forest Lawn Park Solid Village
124 42 130 87 181 124 126
Wasteland Water
129 127
#Попіксельно витягуємо дані в межах учбових полігонів та формуємо зведену таблицю значень з супутників та відповідних класів.
#Приклад програмного коду взято з: http://amsantac.co/blog/en/2015/11/28/classification-r.html
dfAll <- data.frame(matrix(vector(), nrow = 0, ncol = length(names(ImageStack)) + 1))
for (i in 1:length(unique(trainData[["ClassInt"]]))){
category <- unique(trainData[["ClassInt"]])[i]
categorymap <- trainData[trainData[["ClassInt"]] == category,]
#запускаємо кластер багатопоточних обчислень
beginCluster()
dataSet <- extract(ImageStack, categorymap)
#відключаємо кластер багатопоточних обчислень
endCluster()
dataSet <- dataSet[!unlist(lapply(dataSet, is.null))]
dataSet <- lapply(dataSet, function(x){cbind(x, ClassInt = as.numeric(rep(category, nrow(x))))})
df <- do.call("rbind", dataSet)
dfAll <- rbind(dfAll, df)
}
Loading required namespace: parallel
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
4 cores detected, using 3
Using cluster with 3 nodes
#Повертаємо символьні найменування класів в отриману кроком вище таблицю
ClassDF <- data.frame(Class = levels(factor(trainData@data$Class)), ClassInt = seq(1:9))
dfAll <- left_join(dfAll, ClassDF)
Joining, by = c("ClassInt", "Class")
LearnDF <- dplyr::select(dfAll, -ClassInt)
#Перевіряємо кількість пікселів кожного класу в отриманій таблиці учбової вибірки
summary(factor(LearnDF$Class))
Bulrush Burned Area Forest Lawn Park Solid Village
2398 871 2671 1961 3615 4366 3153
Wasteland Water
3049 3444
#Будуємо гістограми зі статистичними показниками виділених класів
# png("Histogram_Gazon_WithoutDegLawn_20170901.png", width = 297,
# height = 210, units = "mm", res = 150)
tbl_df(LearnDF) %>%
reshape2::melt(id = "Class") %>%
ggplot(aes(x = value, fill = variable)) +
geom_histogram(position = "identity") +
facet_wrap( ~ variable, nrow = 3, scales = "free") +
labs(y = "кількість випадків\n",
x = "\nвеличини значень оптичних та радарних діапазонів",
title = "Розподіл значень радарних та оптичних сигналів\nв межах учбових полігонів умовних класів території Кривого Рогу",
caption = "дані космічних апаратів\nSentinel-1A, Sentinel-2A, Landsat-8\n30 квітня та 7-12 серпня 2017 року") +
theme(plot.title = element_text(hjust = 0.5),
text = element_text(family = "FreeSans",
face = "plain", size = 12, colour = "firebrick4", lineheight = 0.9),
legend.position = "none",
axis.text.x = element_text(colour = "gray15", face="bold",
size= 8, angle = 0, vjust = 0.5, hjust = 0.5),
axis.text.y = element_text(colour = "gray15", face="bold",
size= 10, angle = 0, vjust = 0.5, hjust = 1),
axis.ticks = element_line(colour = "orange", size = 0.1),
plot.background = element_rect(fill = "gray95"),
panel.grid.major = element_line(colour = "orange", size = 0.1),
panel.grid.minor = element_line(colour = "gray90"),
panel.background=element_rect(fill="gray95"))

# dev.off()
#Будуємо діаграму зі статистичними показниками виділених класів
# png("Boxplot_Gazon_WithoutDegLawn_20170901.png", width = 297,
# height = 210, units = "mm", res = 150)
tbl_df(LearnDF) %>%
reshape2::melt(id = "Class") %>%
ggplot(aes(y = value, x = Class, colour = variable)) +
geom_boxplot(outlier.size = 0.5) +
coord_flip() +
facet_wrap( ~variable, nrow = 3, scales = "free_x") +
labs(y = "величини значень оптичних та радарних діапазонів\n",
x = "\n",
title = "Радарні та оптичні властивості\nумовних класів території в межах Кривого Рогу",
caption = "дані космічних апаратів\nSentinel-1A, Sentinel-2A, Landsat-8\n30 квітня та 7-12 серпня 2017 року") +
theme(plot.title = element_text(hjust = 0.5),
text = element_text(family = "FreeSans",
face = "plain", size = 12, colour = "firebrick4", lineheight = 0.9),
legend.position = "none",
axis.text.x = element_text(colour = "gray15", face="bold",
size= 8, angle = 0, vjust = 0.5, hjust = 0.5),
axis.text.y = element_text(colour = "gray15", face="bold",
size= 10, angle = 0, vjust = 0.5, hjust = 1),
axis.ticks = element_line(colour = "orange", size = 0.1),
plot.background = element_rect(fill = "gray95"),
panel.grid.major = element_line(colour = "orange", size = 0.1),
panel.grid.minor = element_line(colour = "gray90"),
panel.background=element_rect(fill="gray95"))

#dev.off()
Далі перед нами постає проблема. Справа у тому, що навіть за умови попіксельного розбиття первинних учбових полігонів, порівняно мало навчальних об’єктів для класу Burned Area. У якості експерименту я вирішив зробити вибірку з поверненням, щоб досягти умови врівноваженості класів та 1000 навчальних об’єктів для кожного класу. Таким чином, кількість об’єктів для класу Burned Area було штучно збільшено в 1,14 рази.
LearnDF$num <- c(1:nrow(LearnDF))
#Формуємо робочу таблицю навчальної вибірки,
#вказуємо, що вибірка повинна містити по 1000 об'єктів кожного класу
#та наповнюватись за методом "поверненого шару"
set.seed(12210)
LearnDF %>% group_by(Class) %>%
sample_n(size = 1000, replace = TRUE) %>%
ungroup(Class) %>%
mutate(Class = factor(Class)) -> LearnDF.sample
#Формуємо тестову вибірку
LearnDF$Sample <- ifelse(LearnDF$num %in% LearnDF.sample$num, "Learn", "Test")
LearnDF %>% filter(Sample == "Test") %>% dplyr::select(-c(num, Sample)) -> LearnDF.test
#Прибираємо більше не потрібне поле num в таблиці LearnDF.sample
LearnDF.sample %>% dplyr::select(-c(num, Sample)) -> LearnDF.sample
#Дивимось відсоток записів у навчальній та тестовій вибірках
round(100 * (nrow(LearnDF.sample)/nrow(LearnDF)), 0)
[1] 35
round(100 * (nrow(LearnDF.test)/nrow(LearnDF)), 0)
[1] 71
#Цілком логічно те, що у нас вийде більше 100 відсотків: ми формували навчальну вибірку з поверненням і деякі рядки було взято по декілька разів
#Завантажуємо пакет Random Forest
library(randomForest)
randomForest 4.6-12
Type rfNews() to see new features/changes/bug fixes.
Attaching package: ‘randomForest’
The following object is masked from ‘package:ggplot2’:
margin
The following object is masked from ‘package:dplyr’:
combine
#Запускаємо моделювання та вказуємо робочі параметри процесу моделювання
set.seed(12210)
RF_model_tmp <- randomForest(Class ~., data = LearnDF.sample,
replace = TRUE,
nodesize = 2,
importance = TRUE,
mtry = 3,
ntree = 500,
do.trace = 20)
ntree OOB 1 2 3 4 5 6 7 8 9
20: 5.70% 5.70% 0.30% 4.30% 8.20% 15.40% 5.31% 5.30% 5.70% 1.10%
40: 4.89% 4.60% 0.20% 3.70% 5.60% 13.40% 4.70% 4.80% 6.00% 1.00%
60: 4.66% 4.50% 0.20% 3.90% 5.50% 12.70% 4.70% 4.10% 5.30% 1.00%
80: 4.40% 4.40% 0.20% 3.80% 5.10% 12.30% 4.30% 3.80% 4.70% 1.00%
100: 4.37% 4.10% 0.20% 3.70% 5.60% 12.20% 4.20% 3.50% 4.80% 1.00%
120: 4.28% 4.40% 0.20% 3.20% 5.50% 11.70% 4.10% 3.60% 4.80% 1.00%
140: 4.33% 4.30% 0.20% 3.50% 5.40% 12.30% 4.30% 3.40% 4.60% 1.00%
160: 4.34% 4.20% 0.10% 3.50% 5.60% 12.20% 4.40% 3.40% 4.60% 1.10%
180: 4.20% 4.10% 0.10% 3.50% 5.30% 11.70% 4.10% 3.30% 4.60% 1.10%
200: 4.26% 4.20% 0.10% 3.40% 5.40% 12.20% 4.10% 3.10% 4.60% 1.20%
220: 4.26% 4.30% 0.10% 3.10% 5.70% 12.10% 4.40% 2.90% 4.50% 1.20%
240: 4.18% 4.10% 0.10% 3.30% 5.70% 11.90% 4.00% 2.90% 4.40% 1.20%
260: 4.19% 4.10% 0.10% 3.20% 5.60% 12.10% 4.00% 3.00% 4.40% 1.20%
280: 4.13% 4.10% 0.10% 3.40% 5.40% 11.70% 3.80% 3.10% 4.40% 1.20%
300: 4.23% 4.10% 0.10% 3.50% 5.60% 11.80% 4.10% 3.40% 4.40% 1.10%
320: 4.20% 4.10% 0.10% 3.30% 5.60% 11.80% 4.00% 3.30% 4.40% 1.20%
340: 4.18% 4.20% 0.10% 3.30% 5.60% 11.80% 4.10% 3.00% 4.30% 1.20%
360: 4.17% 4.00% 0.10% 3.30% 5.50% 11.60% 4.40% 3.10% 4.30% 1.20%
380: 4.14% 4.00% 0.10% 3.20% 5.40% 11.80% 4.20% 2.90% 4.50% 1.20%
400: 4.12% 4.10% 0.10% 3.20% 5.50% 11.60% 4.10% 3.00% 4.30% 1.20%
420: 4.13% 4.10% 0.10% 3.20% 5.40% 11.60% 4.30% 2.90% 4.40% 1.20%
440: 4.16% 4.10% 0.10% 3.40% 5.40% 11.60% 4.30% 2.90% 4.40% 1.20%
460: 4.13% 4.10% 0.10% 3.20% 5.40% 11.70% 4.10% 3.00% 4.40% 1.20%
480: 4.17% 4.10% 0.10% 3.20% 5.40% 11.80% 4.20% 3.10% 4.40% 1.20%
500: 4.17% 4.10% 0.10% 3.30% 5.40% 11.60% 4.30% 3.10% 4.40% 1.20%
#Дивимось результат моделювання
RF_model_tmp
Call:
randomForest(formula = Class ~ ., data = LearnDF.sample, replace = TRUE, nodesize = 2, importance = TRUE, mtry = 3, ntree = 500, do.trace = 20)
Type of random forest: classification
Number of trees: 500
No. of variables tried at each split: 3
OOB estimate of error rate: 4.17%
Confusion matrix:
Bulrush Burned Area Forest Lawn Park Solid Village Wasteland Water
Bulrush 959 0 1 2 34 0 0 1 3
Burned Area 0 999 0 0 0 0 0 1 0
Forest 1 0 967 0 30 0 1 0 1
Lawn 2 0 0 946 12 13 18 8 1
Park 13 0 49 19 884 6 26 0 3
Solid 0 0 0 14 4 957 8 14 3
Village 0 0 0 7 19 5 969 0 0
Wasteland 2 1 2 25 11 2 1 956 0
Water 1 0 0 1 7 3 0 0 988
class.error
Bulrush 0.041
Burned Area 0.001
Forest 0.033
Lawn 0.054
Park 0.116
Solid 0.043
Village 0.031
Wasteland 0.044
Water 0.012
#Виконуємо класифікацію для всієї території Кривого Рогу та фіксуємо час виконання
beginCluster()
4 cores detected, using 3
system.time(Gazon_RF_tmp <- clusterR(ImageStack, raster::predict, args = list(model = RF_model_tmp)))
user system elapsed
2.660 0.592 164.389
endCluster()
#Дивимось інформацію щодо інформативності предикторів
varImpPlot(RF_model_tmp, sort = TRUE, main = "Інформативність предикторів")

#Дивимось інформацію про кількість росщеплення дерев на кожному з предикторів
varUsed(RF_model_tmp, by.tree = FALSE, count = TRUE)
[1] 16757 15528 16395 16753 16718 16834 16380 18462 19666 19130 22066 21949 20784 20490
[15] 19541
plot(RF_model_tmp, lwd = 2, col = rainbow(10))
legend("topright", colnames(RF_model_tmp$err.rate), col = rainbow(10), cex = 0.8, fill = rainbow(10))

#Записуємо відокремлений растровий файл з результатами класифікації
writeRaster(Gazon_RF_tmp, "/home/geka/Documents/ZhurnRozslid/DataStory/Ecology/Urban/Gazon20170808/WithoutDegLawn/Gazon20170808_noDegLawn_tmp.sdat", format = "SAGA", overwrite = TRUE)
#Перевіряємо результат класифікації на "тестовій" вибірці
Gazon_DF.predict_tmp <- predict(RF_model_tmp, LearnDF.test)
table(Gazon_DF.predict_tmp, LearnDF.test$Class)
Gazon_DF.predict_tmp Bulrush Burned Area Forest Lawn Park Solid Village Wasteland Water
Bulrush 1504 0 3 2 24 0 0 2 4
Burned Area 0 277 0 0 0 0 0 0 0
Forest 3 0 1738 1 200 0 0 2 2
Lawn 7 0 1 1077 48 101 16 83 2
Park 70 0 67 17 2377 17 58 14 7
Solid 0 0 0 29 10 3258 12 13 8
Village 0 0 2 39 78 29 2222 5 0
Wasteland 2 3 0 9 4 45 0 2072 1
Water 7 0 5 0 4 14 0 0 2554
#Обчислюємо похибку класифікації на "тестовій"" вибірці
sum(diag(table(Gazon_DF.predict_tmp, LearnDF.test$Class)))/sum(table(Gazon_DF.predict_tmp, LearnDF.test$Class))
[1] 0.9410436
#!!!слово "тестова" я навмисно взяв у лапки. Це не чиста тестова вибірка. Через малу кількість об'єктів для деяких класів ми штучно взяли ці об'єкти по 2-3-5 разів. Тому ймовірно, що для ця цих класів у "тестовій" вибірці не залишилось унікальних об'єктів. А для класу Burned Area точно не залишилось унікальних об'єктів у тестовій вибірці
Подальша робота з отриманим файлом класифікованих типів території виконується в середовищі геоінформаційних систем. Зокрема, я використав базові можливості ГІС SAGA для проведення згладжувальної фільтрації отриманого растру класифікації. При цьому було усунено одно-двопіксельні “артефакти”. Для обчислення площ та іншої базової статистики я також використав ГІС SAGA. Для “поліграфічного” оформлення результатів я використовую базові можливості ГІС QGIS.
Стосовно загальної точності моделі: в загальних рисах доволі точно повторює особливості міської території: райони приватного сектору, окремі висотні будинки, зарослі очеретів. Трапляються поодинокі місця, які знаходяться у затінку як для оптичних і радарних супутників, так і для Сонця. Ці місця часто розпізнаються як “Вода”. Особливо це стосується східних бортів деяких великих криворізьких кар’єрів. Також спостерігаються пікселі класу “Очерети” у зовсім нехарактерних місцях. Скоріше за все — це щільна кустарникова рослинність. Це потребує перевірки на місцевості.
LS0tCnRpdGxlOiAi0JrQu9Cw0YHQuNGE0ZbQutCw0YbRltGPINC70LDQvdC00YjQsNGE0YLQvdC+0LPQviDQv9C+0LrRgNC40LLRgyDQt9CwINC00L7Qv9C+0LzQvtCz0L7RjiDQsNC70LPQvtGA0LjRgtC80YMgUmFuZG9tIEZvcmVzdCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoK0J7RgdC90L7QstC90L7RjiDQvNC10YLQvtGOINC00L7RgdC70ZbQtNC20LXQvdC90Y8g0LHRg9C70L4g0LLQuNC30L3QsNGH0LjRgtC4INCyINC80LXQttCw0YUg0JrRgNC40LLQvtCz0L4g0KDQvtCz0YMg0LfQsNCz0LDQu9GM0L3RgyDQv9C70L7RidGDINGC0LXRgNC40YLQvtGA0ZbRlywg0Y/QutGDINC/0L7QutGA0LjRgtC+ICLQttC40LLQvtGOIiAo0L3QtSDQt9Cw0YHQvtGF0LvQvtGOKSDRgNC+0YHQu9C40L3QvdGW0YHRgtGOLiDQn9GA0Lgg0YbRjNC+0LzRgyDQvtGB0L7QsdC70LjQstC40Lwg0LfQsNCy0LTQsNC90L3Rj9C8INCx0YPQu9C+INCy0LjQvtC60YDQtdC80LjRgtC4INGC0LXRgNC40YLQvtGA0ZbRlywg0Y/QutGWINC/0L7QutGA0LjRgtGWINC00LXRgNC10LLQvdC+0Y4g0YDQvtGB0LvQuNC90L3RltGB0YLRji4g0JTQu9GPINGG0YzQvtCz0L4g0YPQv9GA0L7QtNC+0LLQtiDQtNC10LrRltC70YzQutC+0YUg0LTQvdGW0LIg0Y8g0LLRltC30YPQsNC70YzQvdC+INCy0LjQstGH0LDQsiDRhNCw0LrRgtC40YfQvdGWINC00LDQvdGWINC/0YDQviDRgdGC0LDQvSDQs9Cw0LfQvtC90ZbQsiwg0YHQutCy0LXRgNGW0LIsINC/0YPRgdGC0LjRgNGW0LIg0YLQsCDRltC90YjQuNGFINC+0LEn0ZTQutGC0ZbQsiDRgyDQmtGA0LjQstC+0LzRgyDQoNC+0LfRli4g0J/RltC0INGH0LDRgSDQstGW0LfRg9Cw0LvRjNC90L7Qs9C+INC+0LHRgdGC0LXQttC10L3QvdGPINGB0YLQsNC70L4g0LfRgNC+0LfRg9C80ZbQu9C40LwsINGJ0L4g0LvQuNGI0LUg0LzQsNC70LAg0YfQsNGB0YLQutCwINCy0LvQsNGB0L3QtSDQs9Cw0LfQvtC90ZbQsiDQv9GA0LXQtNGB0YLQsNCy0LvQtdC90LAgItC20LjQstC+0Y4iINGC0YDQsNCy0L7Rji4g0JHRltC70YzRiNGW0YHRgtGMINGB0L/QvtGB0YLQtdGA0LXQttC10L3QuNGFINC80L3QvtGOINC00ZbQu9GP0L3QvtC6INC90LXRgdC70Lgg0LDQsdC+INCy0LXQu9GM0LzQuCDQv9GA0LjQs9C90ZbRh9C10L3Rgywg0LDQsdC+INCy0LfQsNCz0LDQu9GWINCy0LjRgdC+0YXQu9GDINGC0YDQsNCyJ9GP0L3RgyDRgNC+0YHQu9C40L3QvdGW0YHRgtGMLiDQotCw0LrQvtC2INGB0YLQsNC70L4g0LfRgNC+0LfRg9C80ZbQu9C40LwsINGJ0L4g0LIg0L7QutGA0LXQvNC40Lkg0LrQu9Cw0YEg0YLQtdGA0LjRgtC+0YDRltGXINGC0YDQtdCx0LAg0LLQuNC90LXRgdGC0Lgg0L/Rg9GB0YLQuNGA0ZYg0YLQsCDQvtGH0LXRgNC10YLQuC4g0J/Rg9GB0YLQuNGA0ZYg0LfQtNC10LHRltC70YzRiNC+0LPQviDQstC60YDQuNGC0ZYg0LDQsdC+INCx0LDQs9Cw0YLQvtGA0ZbRh9C90LjQvNC4INCy0LjRgdC+0LrQvtGA0L7RgdC70LjQvNC4INGC0YDQsNCy0LDQvNC4ICjQtNC10YDQtdCy0ZbQuSwg0L/QvtC70LjQvSwg0LDQvNCx0YDQvtC30ZbRjyDRgtC+0YnQviksINCw0LHQviDRgdGD0LzRltGI0YjRjiDQvdC40LfRjNC60L7RgNC+0YHQu9C40YUg0YLQsCDQstC40YHQvtC60L7RgNC+0YHQu9C40YUg0YLRgNCw0LIuINCi0LDQutC+0LYg0LzQsNC50LbQtSDQstGB0Y7QtNC4INC90LAg0L/Rg9GB0YLQuNGA0Y/RhSDRgtGA0LDQv9C70Y/RjtGC0YzRgdGPINC/0L7QvtC00LjQvdC+0LrRliDQtNC10YDQtdCy0LAuINCe0YfQtdGA0LXRgtC4INC30LDQudC80LDRjtGC0Ywg0L7RgdC+0LHQu9C40LLQtSDQvNGW0YHRhtC1INGDINC80ZbRgdGM0LrRltC5INGA0L7RgdC70LjQvdC90L7RgdGC0ZYsINC+0YHQutGW0LvRjNC60Lgg0LLQvtC90Lgg0LLQutCw0LfRg9GO0YLRjCDQvdCwINCx0LvQuNC30YzQutC1INC30L3QsNGF0L7QtNC20LXQvdC90Y8g0pHRgNGD0L3RgtC+0LLQuNGFINCy0L7QtCAo0LfQvtC90Lgg0L/RltC00YLQvtC/0LvQtdC90L3RjykuINCi0LDQutC+0LYg0L7Rh9C10YDQtdGC0LgsINC30YDQvtGB0YLQsNGO0YfQuCDQvdCwINCx0LXRgNC10LPQsNGFINGC0LAg0YMg0LLQvtC00L7QudC80LDRhSwg0LLQutCw0LfRg9GO0YLRjCDQvdCwINGB0YLRg9C/0ZbQvdGMINC30LDQvNGD0LvQtdC90L3RjyDQv9C+0LLQtdGA0YXQvdC10LLQuNGFINCy0L7QtNC+0LnQvC4KCtCn0LXRgNC10Lcg0LzQsNC70YMg0LrRltC70YzQutGW0YHRgtGMICLQttC40LLQuNGFIiDQs9Cw0LfQvtC90ZbQsiDQtNC+0LLQtdC70L7RgdGMINGC0YDQvtGF0Lgg0LfQvNGW0YHRgtC40YLQuCDRgNGW0LLQtdC90Ywg0LTQtdGC0LXQutGC0YPQstCw0L3QvdGPINC60LvQsNGB0YMgItCz0LDQt9C+0L0iLiDQn9GW0LQg0YfQsNGBINC60LvQsNGB0LjRhNGW0LrQsNGG0ZbRlyDQtNC+ICLQs9Cw0LfQvtC90ZbQsiIg0LzQvdC+0Y4g0LHRg9C70L4g0LLRltC00L3QtdGB0LXQvdC+INC90LUg0LvQuNGI0LUg0LLQu9Cw0YHQvdC1ICLQs9Cw0LfQvtC90LgiLCDQsCDQuSDQsdGD0LTRjC3Rj9C60ZYg0LTRltC70Y/QvdC60Lgg0Lcg0L3QuNC30YzQutC+0YDQvtGB0LvQuNC80LggItC20LjQstC40LzQuCIg0YLRgNCw0LLQsNC80LggLSDQtNC+0LPQu9GP0L3Rg9GC0ZYg0YHRgtCw0LTRltC+0L3QuCwg0YfQsNGB0YLQuNC90Lgg0L/Rg9GB0YLQuNGA0ZbQsiwg0LTRltC70Y/QvdC60Lgg0YHRg9GF0L7QtNC+0LvRgyDQsiDQsdC10LfQv9C+0YHQtdGA0LXQtNC90ZbQuSDQsdC70LjQt9GM0LrQvtGB0YLRliDQtNC+INCy0L7QtNC90LjRhSDQvtCxJ9GU0LrRgtGW0LIuCgrQl9Cw0LPQsNC70L7QvCDQsiDRgNCw0LzQutCw0YUg0LTQvtGB0LvRltC00LbQtdC90L3RjyDQsdGD0LvQviDQstC40LTRltC70LXQvdC+IDkg0YPQvNC+0LLQvdC40YUg0LrQu9Cw0YHRltCyOgoKLSAi0J7Rh9C10YDQtdGC0LgiICgqKkJ1bHJ1c2gqKikgLS0tINGB0YPRhtGW0LvRjNC90ZYg0LfQsNGA0L7RgdGC0ZYg0L7Rh9C10YDQtdGC0ZbQsjsKCi0gItCS0LjQv9Cw0LvQtdC90LAg0YLQtdGA0LjRgtC+0YDRltGPIiAoKipCdXJuZWQgQXJlYSoqKSAtLS0g0LTRltC70Y/QvdC60Lgg0LLQuNCz0L7RgNGW0LvQvtGXINCy0L3QsNGB0LvRltC00L7QuiDQv9C+0LbQtdC2INGA0L7RgdC70LjQvdC90L7RgdGC0ZYuINCm0LXQuSDQutC70LDRgSDQvtC60YDQtdC80L4g0LLQuNC00ZbQu9C10L3QviDRh9C10YDQtdC3INGC0LUsINGJ0L4g0L/RgNC+0YLRj9Cz0L7QvCDQvdC10YLRgNC40LLQsNC70L7Qs9C+INGH0LDRgdGDINCy0LjQs9C+0YDRltC70Lgg0LTRltC70Y/QvdC60Lgg0LfQsNGA0L7RgdGC0LDRjtGC0Ywg0YLRgNCw0LLQsNC80Lgg0YLQsCDQv9C10YDQtdGF0L7QtNGP0YLRjCDQtNC+INC60LvQsNGB0YMgItCz0LDQt9C+0L0iINCw0LHQviAi0L/Rg9GB0YLQuNGAIjsKCi0gItCb0ZbRgSIgKCoqRm9yZXN0KiopIC0tLSDRidGW0LvRjNC90ZYg0LvRltGB0L7QstGWINC90LDRgdCw0LTQttC10L3QvdGPINGW0Lcg0LrRg9GJ0LDQvNC4INGC0LAg0YLRgNCw0LLQsNC80Lg7CgotICLQk9Cw0LfQvtC9IiAoKipMYXduKiopIC0tLSDQtNGW0LvRj9C90LrQuCDQvdC40LfRjNC60L7RgtGA0LDQsifRjyDQtyDQvdC+0YDQvNCw0LvRjNC90L7RjiAoItC20LjQstC+0Y4iKSDRgNC+0YHQu9C40L3QvdGW0YHRgtGOOwoKLSAi0J/QsNGA0LoiICgqKlBhcmsqKikgLS0tINC00ZbQu9GP0L3QutC4INC3INC90LXRidGW0LvRjNC90LjQvNC4INC90LDRgdCw0LTQttC10L3QvdGP0LzQuCDQtNC10YDQtdCyLiDQkiDRj9C60L7RgdGC0ZYg0LXRgtCw0LvQvtC90YMg0YbRjNC+0LPQviDQutC70LDRgdGDINCy0LfRj9GC0L4g0LzRltGB0YzQutGWINC/0LDRgNC60Lgg0YLQsCDRgdC60LLQtdGA0Lg7CgotICLQotCy0LXRgNC00LAg0L/QvtCy0LXRgNGF0L3RjyIgKCoqU29saWQqKikgLS0tINCx0YPQtNGMLdGP0LrRliDRgtCy0LXRgNC00ZYg0L/QvtCy0LXRgNGF0L3Rljog0LTQvtGA0L7Qs9C4LCDQsdC10YLQvtC9LCDQvtCz0L7Qu9C10L3RliDSkdGA0YPQvdGC0LgsINGB0LrQtdC70YzQvdGWINC/0L7RgNC+0LTQuCwg0LDQvdGC0YDQvtC/0L7Qs9C10L3QvdGWINC+0LEn0ZTQutGC0LggKNC60LDRgCfRlNGA0LgsINCy0ZbQtNCy0LDQu9C4LCDRhdCy0L7RgdGC0L7RgdGF0L7QstC40YnQsCDRgtC+0YnQvikuINCi0L7QsdGC0L4g0LTQviDRhtGM0L7Qs9C+INC60LvQsNGB0YMg0YPQstGW0LnRiNC70Lgg0LLRgdGWINGC0LjQv9C4INGC0LXRgNC40YLQvtGA0ZbQuSwg0Y/QutGWINC90LUg0L/QvtC60YDQuNGC0ZYg0YDQvtGB0LvQuNC90L3RltGB0YLRjiDRgtCwINCy0L7QtNC+0Y47CgotICLQn9GA0LjQstCw0YLQvdC40Lkg0YHQtdC60YLQvtGAIiAoKipWaWxsYWdlKiopIC0tLSDQstC40LHRltGAINGG0YzQvtCz0L4g0LrQu9Cw0YHRgyDQvtCx0YPQvNC+0LLQu9C10L3QuNC5INGB0L/QtdGG0LjRhNGW0YfQvdGW0YHRgtGOINC+0LTQvdC+0L/QvtCy0LXRgNGF0L7QstC+0Zcg0LzRltGB0YzQutC+0Zcg0LfQsNCx0YPQtNC+0LLQuDog0YnRltC70YzQvdCwINGB0YPQvNGW0Ygg0LTQtdGA0LXQsiwg0YLRgNCw0LIsINGC0LLQtdGA0LTQuNGFINC/0L7QstC10YDRhdC+0L3RjCwg0L/QvtCx0YPQtNC+0LIg0YLQsCDRgdC/0L7RgNGD0LQuINCi0LDQutCwINGB0YPQvNGW0Ygg0YDRltC30L3QvtGA0L7QtNC90LjRhSDQvtCxJ9GU0LrRgtGW0LIg0YMg0LzQtdC20LDRhSDQvtC00L3QvtCz0L4g0L/RltC60YHQtdC70Y4g0LrQvtGB0LzRltGH0L3QvtCz0L4g0LfQvdGW0LzQutGDINC/0YDQuNC30LLQvtC00LjRgtGMINC00L4g0YHQv9C10YbQuNGE0ZbRh9C90L7Qs9C+INCy0ZbQtNCx0LjRgtGC0Y8g0Y/QuiDQvtC/0YLQuNGH0L3QuNGFINGC0LDQuiDRliDRgNCw0LTQsNGA0L3QuNGFINGF0LLQuNC70Yw7CgotICLQn9GD0YHRgtC40YAiICgqKldhc3RlbGFuZCoqKSAtLS0g0LTRltC70Y/QvdC60Lgg0ZbQtyDRgdGD0LzRltGI0YjRjiDQvdC40LfRjNC60L7RgNC+0YHQu9C40YUg0YLQsCDQstC40YHQvtC60L7RgNC+0YHQu9C40YUg0YLRgNCw0LIg0ZYg0L/QvtC+0LTQuNC90L7QutC40YUg0LTQtdGA0LXQsi4g0JfQtNC10LHRltC70YzRiNC+0LPQviAtLS0g0YbQtSDQvdC10LTQvtCz0LvRj9C90YPRgtGWINC30LXQvNC10LvRjNC90ZYg0LTRltC70Y/QvdC60LgsINGP0LrRliDRgdGF0LjQu9GM0L3RliDQtNC+INGB0LDQvNC+0LfQsNGA0L7RgdGC0LDQvdC90Y8g0YDQvtGB0LvQuNC90L3RltGB0YLRjjsKCi0gItCS0L7QtNCwIiAoKipXYXRlcioqKSAtLS0g0LHRg9C00Ywt0Y/QutGWINCy0ZbQtNC60YDQuNGC0ZYg0LLQvtC00L3RliDQv9C+0LLQtdGA0YXQvdGWICjRgNGW0LrQuCwg0YHRgtCw0LLQutC4LCDQstGW0LTRgdGC0ZbQudC90LjQutC4LCDRhdCy0L7RgdGC0L7RgdGF0L7QstC40YnQsCDRgtC+0YnQvikKCtCSINGP0LrQvtGB0YLRliDQv9C10YDQstC40L3QvdC40YUg0LzQsNGC0LXRgNGW0LDQu9GW0LIg0LLQt9GP0YLQvjoKCi0g0LfQvdGW0LzQvtC6INC60L7RgdC80ZbRh9C90L7Qs9C+INCw0L/QsNGA0LDRgtGDIFNlbnRpbmVsLTFBINCy0ZbQtCA3INGB0LXRgNC/0L3RjyAyMDE3INGA0L7QutGDIChHUkQpINCyINC/0L7Qu9GP0YDQuNC30LDRhtGW0Y/RhSBWSCDRgtCwIFZWOwoKLSDQutCw0L3QsNC70LggMiwgMywgNCwgNSwgNiwgNywgOCwgOEEsIDExINGC0LAgMTIg0LfQvdGW0LzQutGDINC60L7RgdC80ZbRh9C90L7Qs9C+INCw0L/QsNGA0LDRgtGDIFNlbnRpbmVsLTJBINCy0ZbQtCA4INGB0LXRgNC/0L3RjyAyMDE3INGA0L7QutGDOwoKLSDQutCw0L3QsNC70LggMTAg0YLQsCAxMSDQutC+0YHQvNGW0YfQvdC+0LPQviDQsNC/0LDRgNCw0YLRgyBMYW5kc2F0LTgg0LLRltC0IDEyINGB0LXRgNC/0L3RjyAyMDE3INGA0L7QutGDOwoKLSDQutCw0L3QsNC7IDgg0LfQvdGW0LzQutGDINC60L7RgdC80ZbRh9C90L7Qs9C+INCw0L/QsNGA0LDRgtGDIFNlbnRpbmVsLTJBINCy0ZbQtCAzMCDQutCy0ZbRgtC90Y8gMjAxNyDRgNC+0LrRgy4KCtCU0LvRjyDRgNCw0LTQsNGA0L3QvtCz0L4g0LfQvdGW0LzQutGDINCx0YPQu9C+INC/0YDQvtCy0LXQtNC10L3QviDRgNCw0LTRltC+0LzQtdGC0YDQuNGH0L3RgyDQutC+0YDQtdC60YbRltGOLCDRhNGW0LvRjNGC0YDQsNGG0ZbRjiDRgdC/0LXQutC7LdGI0YPQvNGDICjQtyDQstC40LrQvtGA0LjRgdGC0LDQvdC90Y/QvCDRhNGW0LvRjNGC0YDRgyBHYW1tYSBNYXApLCDQvtCx0YfQuNGB0LvQtdC90L3RjyDRgdC40LvQuCDQstGW0LTQsdC40YLRgtGPINCyINC00LXRhtC40LHQtdC70LDRhSDRgtCwINCz0LXQvtC80LXRgtGA0LjRh9C90YMg0LrQvtGA0LXQutGG0ZbRjiAoUmFuZ2UtRG9wcGxlcikuINCU0LvRjyDRhtGM0L7Qs9C+INCx0YPQu9C+INCy0LjQutC+0YDQuNGB0YLQsNC90L4g0L/RgNC+0LPRgNCw0LzQvdC40Lkg0LfQsNGB0ZbQsSBTTkFQIChTZW50aW5lbHMgQXBwbGljYXRpb24gUGxhdGZvcm0pLgoK0JfQvdGW0LzQutC4INC+0L/RgtC40YfQvdC40YUg0YHRg9C/0YPRgtC90LjQutGW0LIg0L7QsdGA0L7QsdC70LXQvdC+INC3INCy0LjQutC+0YDQuNGB0YLQsNC90L3Rj9C8INC80L7QtNGD0LvRjiBTZW1pLUF1dG9tYXRpYyBDbGFzc2lmaWNhdGlvbiBQbHVnaW4g0LPQtdC+0ZbQvdGE0L7RgNC80LDRhtGW0LnQvdC+0Zcg0YHQuNGB0YLQtdC80LggUUdJUyAoU2VudGluZWwtMkEpINGC0LAgU0FHQSBHSVMgKExhbmRzYXQtOCkuCgrQn9GW0YHQu9GPINC/0ZbQtNCz0L7RgtC+0LLRh9C+0LPQviDQvtCx0YDQvtCx0LvQtdC90L3RjyDQstGB0ZYg0LfQvdGW0LzQutC4INCx0YPQu9C+INC30LDQstCw0L3RgtCw0LbQtdC90L4g0LIg0LPQtdC+0ZbQvdGE0L7RgNC80LDRhtGW0LnQvdGDINGB0LjRgdGC0LXQvNGDIFNBR0EuINCi0LDQvCDQstC40LrQvtC90LDQvdC+INC/0L7QutCw0L3QsNC70YzQvdC1INC+0LEn0ZTQtNC90LDQvdC90Y8g0LTQstC+0YUg0LPRgNCw0L3Rg9C7INC30L3RltC80LrRltCyINC60L7RgdC80ZbRh9C90L7Qs9C+INCw0L/QsNGA0LDRgtGDIFNlbnRpbmVsLTJBIChUV1Qg0YLQsCBVV1UpLCDQvtCx0YDRltC30LDQvdC90Y8g0LLRgdGW0YUg0LfQvdGW0LzQutGW0LIg0L/QviDQutC+0L3RgtGD0YDRgyDQmtGA0LjQstC+0LPQviDQoNC+0LPRgyAo0LrQvtC90YLRg9GAINCy0LfRj9GC0L4g0Lcg0L/RgNC+0LXQutGC0YMgT3BlblN0cmVldE1hcCksINC/0YDQuNCy0LXQtNC10L3QvdGPINCy0YHRltGFINC30L3RltC80LrRltCyINC00L4g0YDQvtC30LzRltGA0YMg0L/RltC60YHQtdC70Y4gMTDQpTEwINC8LiDQn9GA0Lgg0YbRjNC+0LzRgyDQsiDRj9C60L7RgdGC0ZYgItC+0YHQvdC+0LLQuCIg0LLQuNC60L7RgNC40YHRgtC+0LLRg9Cy0LDQstGB0Y8g0LfQvdGW0LzQvtC6INC60L7RgdC80ZbRh9C90L7Qs9C+INCw0L/QsNGA0LDRgtGDIFNlbnRpbmVsLTJBLgoK0JTQu9GPINGE0L7RgNC80YPQstCw0L3QvdGPINC90LDQstGH0LDQu9GM0L3QvtGXINCy0LjQsdGW0YDQutC4INC+0LEn0ZTQutGC0ZbQsiDQt9GA0L7QsdC70LXQvdC+INGB0LXQs9C80LXQvdGC0LDRhtGW0Y4g0LTQvtGB0LvRltC00LbRg9Cy0LDQvdC+0Zcg0YLQtdGA0LjRgtC+0YDRltGXINCx0LDQt9C+0LLQuNC8INC80LXRgtC+0LTQvtC8IE9iamVjdCBCYXNlZCBJbWFnZSBTZWdtZW50YXRpb24g0LPQtdC+0ZbQvdGE0L7RgNC80LDRhtGW0LnQvdC+0Zcg0YHQuNGB0YLQtdC80LggU0FHQS4g0J/QvtGC0ZbQvCDQvdC10LfQvdCw0YfQvdGW0Lkg0YfQsNGB0YLQuNC90ZYg0L/QvtC70ZbQs9C+0L3RltCyINC+0YLRgNC40LzQsNC90L7Qs9C+INGI0LXQudC/LdGI0LDRgNGDINC/0YDQuNC/0LjRgdCw0L3QviDQvtC30L3QsNGH0LXQvdGWINCy0LjRidC1INC60LvQsNGB0Lgg0YLQtdGA0LjRgtC+0YDRltGXLiDQl9Cw0LPQsNC70L7QvCDQsdGD0LvQviDQv9GA0L7QutC70LDRgdC40YTRltC60L7QstCw0L3QviAxMDcwINC/0L7Qu9GW0LPQvtC90ZbQsi4g0JrRltC70YzQutGW0YHRgtGMINC/0L7Qu9GW0LPQvtC90ZbQsiDQt9CwINC60LvQsNGB0LDQvNC4INC30L3QsNGH0L3QviDRgNGW0LfQvdC40YLRjNGB0Y8uCgrQndCw0YHRgtGD0L/QvdGWINC60YDQvtC60Lgg0LLQuNC60L7QvdGD0LLQsNC70LjRgdGMINCyINGB0LXRgNC10LTQvtCy0LjRidGWINC80L7QstC4INC/0YDQvtCz0YDQsNC80YPQstCw0L3QvdGPIFIuINCd0LjQttGH0LUg0LzRltGB0YLRj9GC0YzRgdGPINGB0LrRgNC40L/RgtC4LCDRj9C60LjQvNC4INCy0LjQutC+0L3Rg9Cy0LDQstGB0Y8g0LLQtdGB0Ywg0L/RgNC+0YbQtdGBINC+0LHRh9C40YHQu9C10L3QvdGPINGC0LAg0L/QtdGA0LXQstGW0YDQutC4INC00LDQvdC40YUuCgpgYGB7cn0KI9CX0LDQstCw0L3RgtCw0LbRg9GU0LzQviDQv9C+0YLRgNGW0LHQvdGWINC/0LDQutC10YLQuApsaWJyYXJ5KHBseXIpI9GB0LDQvNC1INCyINGC0LDQutGW0Lkg0L/QvtGB0LvRltC00L7QstC90L7RgdGC0ZY6INGB0L/QvtGH0LDRgtC60YMgcGx5ciwg0L/QvtGC0ZbQvCBkcGx5ciEKbGlicmFyeShkcGx5cikKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkoZ2dwbG90MikKYGBgCgpgYGB7cn0KI9CS0YHRgtCw0L3QvtCy0LvRjtGU0LzQviDQtNC40YDQtdC60YLQvtGA0ZbRjiDQtNC70Y8g0LrQtdGI0YPQstCw0L3QvdGPICLQstC10LvQuNC60LjRhSDRgNCw0YHRgtGA0ZbQsiIKcmFzdGVyT3B0aW9ucyh0bXBkaXIgPSAiL2hvbWUvZ2VrYS9zc2QvTGFyZ2VUTVAvIikKYGBgCgpgYGB7cn0KI9CX0LDQstCw0L3RgtCw0LbRg9GU0LzQviDRgyDQstC40LPQu9GP0LTRliDQvtC60YDQtdC80LjRhSDQvtCxJ9GU0LrRgtGW0LIg0LLRgdGWINGB0YPQv9GD0YLQvdC40LrQvtCy0ZYg0LzQsNGC0LXRgNGW0LDQu9C4CkltYWdlX1MyQjIgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwMl9LclIuc2RhdCIpCkltYWdlX1MyQjMgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwM19LclIuc2RhdCIpCkltYWdlX1MyQjQgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwNF9LclIuc2RhdCIpCkltYWdlX1MyQjUgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwNV9LclIuc2RhdCIpCkltYWdlX1MyQjYgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwNl9LclIuc2RhdCIpCkltYWdlX1MyQjcgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwN19LclIuc2RhdCIpCkltYWdlX1MyQjggPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IwOF9LclIuc2RhdCIpCkltYWdlX1MyQjhBIDwtIHJhc3RlcigiL2hvbWUvZ2VrYS9Eb2N1bWVudHMvWmh1cm5Sb3pzbGlkL0RhdGFTdG9yeS9FY29sb2d5L1VyYmFuL0dhem9uMjAxNzA4MDgvUzJfVFdUX1VXVV8yMDE3MDgwOF9COEFfS3JSLnNkYXQiKQpJbWFnZV9TMkIxMSA8LSByYXN0ZXIoIi9ob21lL2dla2EvRG9jdW1lbnRzL1podXJuUm96c2xpZC9EYXRhU3RvcnkvRWNvbG9neS9VcmJhbi9HYXpvbjIwMTcwODA4L1MyX1RXVF9VV1VfMjAxNzA4MDhfQjExX0tyUi5zZGF0IikKSW1hZ2VfUzJCMTIgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwODA4X0IxMl9LclIuc2RhdCIpCkltYWdlX0w4QjEwIDwtIHJhc3RlcigiL2hvbWUvZ2VrYS9Eb2N1bWVudHMvWmh1cm5Sb3pzbGlkL0RhdGFTdG9yeS9FY29sb2d5L1VyYmFuL0dhem9uMjAxNzA4MDgvUlRfTEMwOF9MMVRQXzE3ODAyN18yMDE3MDgxMl8yMDE3MDgxMl8wMV9SVF9CMTBfS3JSLnNkYXQiKQpJbWFnZV9MOEIxMSA8LSByYXN0ZXIoIi9ob21lL2dla2EvRG9jdW1lbnRzL1podXJuUm96c2xpZC9EYXRhU3RvcnkvRWNvbG9neS9VcmJhbi9HYXpvbjIwMTcwODA4L1JUX0xDMDhfTDFUUF8xNzgwMjdfMjAxNzA4MTJfMjAxNzA4MTJfMDFfUlRfQjExX0tyUi5zZGF0IikKSW1hZ2VfUzFWSCA8LSByYXN0ZXIoIi9ob21lL2dla2EvRG9jdW1lbnRzL1podXJuUm96c2xpZC9EYXRhU3RvcnkvRWNvbG9neS9VcmJhbi9HYXpvbjIwMTcwODA4L1MxQV9HUkRIXzIwMTcwODA3X1NpZ21hVkhfZGJfS3JSLnNkYXQiKQpJbWFnZV9TMVZWIDwtIHJhc3RlcigiL2hvbWUvZ2VrYS9Eb2N1bWVudHMvWmh1cm5Sb3pzbGlkL0RhdGFTdG9yeS9FY29sb2d5L1VyYmFuL0dhem9uMjAxNzA4MDgvUzFBX0dSREhfMjAxNzA4MDdfU2lnbWFWVl9kYl9LclIuc2RhdCIpCkltYWdlX1MyQjhBUFIgPC0gcmFzdGVyKCIvaG9tZS9nZWthL0RvY3VtZW50cy9aaHVyblJvenNsaWQvRGF0YVN0b3J5L0Vjb2xvZ3kvVXJiYW4vR2F6b24yMDE3MDgwOC9TMl9UV1RfVVdVXzIwMTcwNDMwX0IwOF9LclIuc2RhdCIpCmBgYAoKYGBge3J9CiPQntCxJ9GU0LTQvdGD0ZTQvNC+INCy0YHRliDQutCw0L3QsNC70Lgg0LIg0L7QtNC40L0g0L7QsSfRlNC60YIKSW1hZ2VTdGFjayA8LSBzdGFjayhJbWFnZV9TMkIyLCBJbWFnZV9TMkIzLCBJbWFnZV9TMkI0LCBJbWFnZV9TMkI1LCBJbWFnZV9TMkI2LAogICAgICAgICAgICAgICAgICAgIEltYWdlX1MyQjcsIEltYWdlX1MyQjgsIEltYWdlX1MyQjhBLCBJbWFnZV9TMkIxMSwgSW1hZ2VfUzJCMTIsCiAgICAgICAgICAgICAgICAgICAgSW1hZ2VfTDhCMTAsIEltYWdlX0w4QjExLCBJbWFnZV9TMVZILCBJbWFnZV9TMVZWLCBJbWFnZV9TMkI4QVBSKQpgYGAKCgpgYGB7cn0KI9Cf0LXRgNC10LnQvNC10L3QvtCy0YPRlNC80L4g0LrQsNC90LDQu9C4INCyINC+0LEn0ZTQtNC90LDQvdC+0LzRgyDQvtCxJ9GU0LrRgtGWCm5hbWVzKEltYWdlU3RhY2spIDwtIGMoIlMyQjIiLCAiUzJCMyIsICJTMkI0IiwgIlMyQjUiLCAiUzJCNiIsICJTMkI3IiwKICAgICAgICAgICAgICAgICAgICAgICAiUzJCOCIsICJTMkI4QSIsICJTMkIxMSIsICJTMkIxMiIsCiAgICAgICAgICAgICAgICAgICAgIkw4QjEwIiwgIkw4QjExIiwgIlMxVkgiLCAiUzFWViIsICJTMkI4QVBSIikKYGBgCgpgYGB7cn0KI9CS0ZbQt9GD0LDQu9GM0L3QviDQv9C10YDQtdCy0ZbRgNGP0ZTQvNC+INCw0LTQtdC60LLQsNGC0L3RltGB0YLRjCDRgtCwINC/0L7QstC90L7RgtGDINC00LDQvdC40YUKcGxvdFJHQihJbWFnZVN0YWNrLCByID0gNywgZyA9IDExLCBiID0gMTQsIHN0cmV0Y2ggPSAiaGlzdCIpCmBgYAoKYGBge3J9CiPQl9Cw0LLQsNC90YLQsNC20YPRlNC80L4g0YjQtdC50L8t0YTQsNC50Lsg0Lcg0L3QsNCy0YfQsNC70YzQvdC40LzQuCDQv9C+0LvRltCz0L7QvdCw0LzQuAp0cmFpblNoYXBlIDwtIHNoYXBlZmlsZSgiL2hvbWUvZ2VrYS9Eb2N1bWVudHMvWmh1cm5Sb3pzbGlkL0RhdGFTdG9yeS9FY29sb2d5L1VyYmFuL0dhem9uMjAxNzA4MDgvU2VnbWVudHNfQ2xhc3Nfbm9EZWdMYXduLnNocCIpCmBgYAoKYGBge3J9CiPQktGW0LTQutC40LTQsNGU0LzQviAi0L/QvtGA0L7QttC90ZYiINC/0L7Qu9GW0LPQvtC90LggLSDRgtGWLCDRj9C60LjQvCDQvdC1INC/0YDQuNGB0LLQvtGO0LLQsNC70L7RgdGMINC20L7QtNC90LjRhSDQutC70LDRgdGW0LIKdHJhaW5EYXRhIDwtIHRyYWluU2hhcGVbIWlzLm5hKHRyYWluU2hhcGVAZGF0YSRDbGFzcykgLF0KI9Cg0L7QsdC40LzQviDQv9C+0LvQtSDRhtGW0LvQuNGFINGH0LjRgdC10Lsg0Lcg0L3QvtC80LXRgNCw0LzQuCDQutC70LDRgdGW0LIKdHJhaW5EYXRhQGRhdGEkQ2xhc3NJbnQgPC0gYXMuaW50ZWdlcihmYWN0b3IodHJhaW5EYXRhQGRhdGEkQ2xhc3MpKQpgYGAKCmBgYHtyfQoj0J/QtdGA0LXQstGW0YDRj9GU0LzQviDQutGW0LvRjNC60ZbRgdGC0Ywg0L3QsNGP0LLQvdC40YUg0YPRh9Cx0L7QstC40YUg0L/QvtC70ZbQs9C+0L3RltCyINC30LAg0LrQu9Cw0YHQsNC80LgKc3VtbWFyeShmYWN0b3IodHJhaW5EYXRhQGRhdGEkQ2xhc3MpKQpgYGAKCmBgYHtyfQoj0J/QvtC/0ZbQutGB0LXQu9GM0L3QviDQstC40YLRj9Cz0YPRlNC80L4g0LTQsNC90ZYg0LIg0LzQtdC20LDRhSDRg9GH0LHQvtCy0LjRhSDQv9C+0LvRltCz0L7QvdGW0LIg0YLQsCDRhNC+0YDQvNGD0ZTQvNC+INC30LLQtdC00LXQvdGDINGC0LDQsdC70LjRhtGOINC30L3QsNGH0LXQvdGMINC3INGB0YPQv9GD0YLQvdC40LrRltCyINGC0LAg0LLRltC00L/QvtCy0ZbQtNC90LjRhSDQutC70LDRgdGW0LIuIAoj0J/RgNC40LrQu9Cw0LQg0L/RgNC+0LPRgNCw0LzQvdC+0LPQviDQutC+0LTRgyDQstC30Y/RgtC+INC3OiBodHRwOi8vYW1zYW50YWMuY28vYmxvZy9lbi8yMDE1LzExLzI4L2NsYXNzaWZpY2F0aW9uLXIuaHRtbApkZkFsbCA8LSBkYXRhLmZyYW1lKG1hdHJpeCh2ZWN0b3IoKSwgbnJvdyA9IDAsIG5jb2wgPSBsZW5ndGgobmFtZXMoSW1hZ2VTdGFjaykpICsgMSkpCmZvciAoaSBpbiAxOmxlbmd0aCh1bmlxdWUodHJhaW5EYXRhW1siQ2xhc3NJbnQiXV0pKSl7CiAgY2F0ZWdvcnkgPC0gdW5pcXVlKHRyYWluRGF0YVtbIkNsYXNzSW50Il1dKVtpXQogIGNhdGVnb3J5bWFwIDwtIHRyYWluRGF0YVt0cmFpbkRhdGFbWyJDbGFzc0ludCJdXSA9PSBjYXRlZ29yeSxdCiAgI9C30LDQv9GD0YHQutCw0ZTQvNC+INC60LvQsNGB0YLQtdGAINCx0LDQs9Cw0YLQvtC/0L7RgtC+0YfQvdC40YUg0L7QsdGH0LjRgdC70LXQvdGMCiAgYmVnaW5DbHVzdGVyKCkKICBkYXRhU2V0IDwtIGV4dHJhY3QoSW1hZ2VTdGFjaywgY2F0ZWdvcnltYXApCiAgI9Cy0ZbQtNC60LvRjtGH0LDRlNC80L4g0LrQu9Cw0YHRgtC10YAg0LHQsNCz0LDRgtC+0L/QvtGC0L7Rh9C90LjRhSDQvtCx0YfQuNGB0LvQtdC90YwKICBlbmRDbHVzdGVyKCkKICBkYXRhU2V0IDwtIGRhdGFTZXRbIXVubGlzdChsYXBwbHkoZGF0YVNldCwgaXMubnVsbCkpXQogIGRhdGFTZXQgPC0gbGFwcGx5KGRhdGFTZXQsIGZ1bmN0aW9uKHgpe2NiaW5kKHgsIENsYXNzSW50ID0gYXMubnVtZXJpYyhyZXAoY2F0ZWdvcnksIG5yb3coeCkpKSl9KQogIGRmIDwtIGRvLmNhbGwoInJiaW5kIiwgZGF0YVNldCkKICBkZkFsbCA8LSByYmluZChkZkFsbCwgZGYpCn0KYGBgCgpgYGB7cn0KI9Cf0L7QstC10YDRgtCw0ZTQvNC+INGB0LjQvNCy0L7Qu9GM0L3RliDQvdCw0LnQvNC10L3Rg9Cy0LDQvdC90Y8g0LrQu9Cw0YHRltCyINCyINC+0YLRgNC40LzQsNC90YMg0LrRgNC+0LrQvtC8INCy0LjRidC1INGC0LDQsdC70LjRhtGOCkNsYXNzREYgPC0gZGF0YS5mcmFtZShDbGFzcyA9IGxldmVscyhmYWN0b3IodHJhaW5EYXRhQGRhdGEkQ2xhc3MpKSwgQ2xhc3NJbnQgPSBzZXEoMTo5KSkKZGZBbGwgPC0gbGVmdF9qb2luKGRmQWxsLCBDbGFzc0RGKQpMZWFybkRGIDwtIGRwbHlyOjpzZWxlY3QoZGZBbGwsIC1DbGFzc0ludCkKYGBgCgpgYGB7cn0KI9Cf0LXRgNC10LLRltGA0Y/RlNC80L4g0LrRltC70YzQutGW0YHRgtGMINC/0ZbQutGB0LXQu9GW0LIg0LrQvtC20L3QvtCz0L4g0LrQu9Cw0YHRgyDQsiDQvtGC0YDQuNC80LDQvdGW0Lkg0YLQsNCx0LvQuNGG0ZYg0YPRh9Cx0L7QstC+0Zcg0LLQuNCx0ZbRgNC60LgKc3VtbWFyeShmYWN0b3IoTGVhcm5ERiRDbGFzcykpCmBgYAoKYGBge3J9CiPQkdGD0LTRg9GU0LzQviDQs9GW0YHRgtC+0LPRgNCw0LzQuCDQt9GWINGB0YLQsNGC0LjRgdGC0LjRh9C90LjQvNC4INC/0L7QutCw0LfQvdC40LrQsNC80Lgg0LLQuNC00ZbQu9C10L3QuNGFINC60LvQsNGB0ZbQsgojIHBuZygiSGlzdG9ncmFtX0dhem9uX1dpdGhvdXREZWdMYXduXzIwMTcwOTAxLnBuZyIsIHdpZHRoID0gMjk3LAojICAgICAgaGVpZ2h0ID0gMjEwLCB1bml0cyA9ICJtbSIsIHJlcyA9IDE1MCkKdGJsX2RmKExlYXJuREYpICU+JQogIHJlc2hhcGUyOjptZWx0KGlkID0gIkNsYXNzIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUsIGZpbGwgPSB2YXJpYWJsZSkpICsKICBnZW9tX2hpc3RvZ3JhbShwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsKICBmYWNldF93cmFwKCB+IHZhcmlhYmxlLCBucm93ID0gMywgc2NhbGVzID0gImZyZWUiKSArCiAgbGFicyh5ID0gItC60ZbQu9GM0LrRltGB0YLRjCDQstC40L/QsNC00LrRltCyXG4iLAogICAgICAgeCA9ICJcbtCy0LXQu9C40YfQuNC90Lgg0LfQvdCw0YfQtdC90Ywg0L7Qv9GC0LjRh9C90LjRhSDRgtCwINGA0LDQtNCw0YDQvdC40YUg0LTRltCw0L/QsNC30L7QvdGW0LIiLAogICAgICAgdGl0bGUgPSAi0KDQvtC30L/QvtC00ZbQuyDQt9C90LDRh9C10L3RjCDRgNCw0LTQsNGA0L3QuNGFINGC0LAg0L7Qv9GC0LjRh9C90LjRhSDRgdC40LPQvdCw0LvRltCyXG7QsiDQvNC10LbQsNGFINGD0YfQsdC+0LLQuNGFINC/0L7Qu9GW0LPQvtC90ZbQsiDRg9C80L7QstC90LjRhSDQutC70LDRgdGW0LIg0YLQtdGA0LjRgtC+0YDRltGXINCa0YDQuNCy0L7Qs9C+INCg0L7Qs9GDIiwKICAgICAgIGNhcHRpb24gPSAi0LTQsNC90ZYg0LrQvtGB0LzRltGH0L3QuNGFINCw0L/QsNGA0LDRgtGW0LJcblNlbnRpbmVsLTFBLCBTZW50aW5lbC0yQSwgTGFuZHNhdC04XG4zMCDQutCy0ZbRgtC90Y8g0YLQsCA3LTEyINGB0LXRgNC/0L3RjyAyMDE3INGA0L7QutGDIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkZyZWVTYW5zIiwKICAgICBmYWNlID0gInBsYWluIiwgc2l6ZSA9IDEyLCBjb2xvdXIgPSAiZmlyZWJyaWNrNCIsIGxpbmVoZWlnaHQgPSAwLjkpLAogICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiZ3JheTE1IiwgZmFjZT0iYm9sZCIsCiAgICAgc2l6ZT0gOCwgYW5nbGUgPSAwLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAwLjUpLAogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJncmF5MTUiLCBmYWNlPSJib2xkIiwKICAgICBzaXplPSAxMCwgYW5nbGUgPSAwLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAxKSwKICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJvcmFuZ2UiLCBzaXplID0gMC4xKSwKICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5OTUiKSwKICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJvcmFuZ2UiLCBzaXplID0gMC4xKSwKICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5OTAiKSwKICAgICBwYW5lbC5iYWNrZ3JvdW5kPWVsZW1lbnRfcmVjdChmaWxsPSJncmF5OTUiKSkKIyBkZXYub2ZmKCkKYGBgCgpgYGB7cn0KI9CR0YPQtNGD0ZTQvNC+INC00ZbQsNCz0YDQsNC80YMg0LfRliDRgdGC0LDRgtC40YHRgtC40YfQvdC40LzQuCDQv9C+0LrQsNC30L3QuNC60LDQvNC4INCy0LjQtNGW0LvQtdC90LjRhSDQutC70LDRgdGW0LIKIyBwbmcoIkJveHBsb3RfR2F6b25fV2l0aG91dERlZ0xhd25fMjAxNzA5MDEucG5nIiwgd2lkdGggPSAyOTcsCiMgICAgICBoZWlnaHQgPSAyMTAsIHVuaXRzID0gIm1tIiwgcmVzID0gMTUwKQp0YmxfZGYoTGVhcm5ERikgJT4lCiAgcmVzaGFwZTI6Om1lbHQoaWQgPSAiQ2xhc3MiKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSB2YWx1ZSwgeCA9IENsYXNzLCBjb2xvdXIgPSB2YXJpYWJsZSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMC41KSArCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF93cmFwKCB+dmFyaWFibGUsIG5yb3cgPSAzLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIGxhYnMoeSA9ICLQstC10LvQuNGH0LjQvdC4INC30L3QsNGH0LXQvdGMINC+0L/RgtC40YfQvdC40YUg0YLQsCDRgNCw0LTQsNGA0L3QuNGFINC00ZbQsNC/0LDQt9C+0L3RltCyXG4iLAogICAgICAgeCA9ICJcbiIsCiAgICAgICB0aXRsZSA9ICLQoNCw0LTQsNGA0L3RliDRgtCwINC+0L/RgtC40YfQvdGWINCy0LvQsNGB0YLQuNCy0L7RgdGC0ZZcbtGD0LzQvtCy0L3QuNGFINC60LvQsNGB0ZbQsiDRgtC10YDQuNGC0L7RgNGW0Zcg0LIg0LzQtdC20LDRhSDQmtGA0LjQstC+0LPQviDQoNC+0LPRgyIsCiAgICAgICBjYXB0aW9uID0gItC00LDQvdGWINC60L7RgdC80ZbRh9C90LjRhSDQsNC/0LDRgNCw0YLRltCyXG5TZW50aW5lbC0xQSwgU2VudGluZWwtMkEsIExhbmRzYXQtOFxuMzAg0LrQstGW0YLQvdGPINGC0LAgNy0xMiDRgdC10YDQv9C90Y8gMjAxNyDRgNC+0LrRgyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJGcmVlU2FucyIsCiAgICAgZmFjZSA9ICJwbGFpbiIsIHNpemUgPSAxMiwgY29sb3VyID0gImZpcmVicmljazQiLCBsaW5laGVpZ2h0ID0gMC45KSwKICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyID0gImdyYXkxNSIsIGZhY2U9ImJvbGQiLAogICAgIHNpemU9IDgsIGFuZ2xlID0gMCwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMC41KSwKICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiZ3JheTE1IiwgZmFjZT0iYm9sZCIsCiAgICAgc2l6ZT0gMTAsIGFuZ2xlID0gMCwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMSksCiAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAib3JhbmdlIiwgc2l6ZSA9IDAuMSksCiAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTk1IiksCiAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAib3JhbmdlIiwgc2l6ZSA9IDAuMSksCiAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTkwIiksCiAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD0iZ3JheTk1IikpCiNkZXYub2ZmKCkKYGBgCgrQlNCw0LvRliDQv9C10YDQtdC0INC90LDQvNC4INC/0L7RgdGC0LDRlCDQv9GA0L7QsdC70LXQvNCwLiDQodC/0YDQsNCy0LAg0YMg0YLQvtC80YMsINGJ0L4g0L3QsNCy0ZbRgtGMINC30LAg0YPQvNC+0LLQuCDQv9C+0L/RltC60YHQtdC70YzQvdC+0LPQviDRgNC+0LfQsdC40YLRgtGPINC/0LXRgNCy0LjQvdC90LjRhSDRg9GH0LHQvtCy0LjRhSDQv9C+0LvRltCz0L7QvdGW0LIsINC/0L7RgNGW0LLQvdGP0L3QviDQvNCw0LvQviDQvdCw0LLRh9Cw0LvRjNC90LjRhSDQvtCxJ9GU0LrRgtGW0LIg0LTQu9GPINC60LvQsNGB0YMgKkJ1cm5lZCBBcmVhKi4g0KMg0Y/QutC+0YHRgtGWINC10LrRgdC/0LXRgNC40LzQtdC90YLRgyDRjyDQstC40YDRltGI0LjQsiDQt9GA0L7QsdC40YLQuCDQstC40LHRltGA0LrRgyDQtyDQv9C+0LLQtdGA0L3QtdC90L3Rj9C8LCDRidC+0LEg0LTQvtGB0Y/Qs9GC0Lgg0YPQvNC+0LLQuCDQstGA0ZbQstC90L7QstCw0LbQtdC90L7RgdGC0ZYg0LrQu9Cw0YHRltCyINGC0LAgMTAwMCDQvdCw0LLRh9Cw0LvRjNC90LjRhSDQvtCxJ9GU0LrRgtGW0LIg0LTQu9GPINC60L7QttC90L7Qs9C+INC60LvQsNGB0YMuINCi0LDQutC40Lwg0YfQuNC90L7QvCwg0LrRltC70YzQutGW0YHRgtGMINC+0LEn0ZTQutGC0ZbQsiDQtNC70Y8g0LrQu9Cw0YHRgyAqQnVybmVkIEFyZWEqINCx0YPQu9C+INGI0YLRg9GH0L3QviDQt9Cx0ZbQu9GM0YjQtdC90L4g0LIgMSwxNCDRgNCw0LfQuC4KCmBgYHtyfQpMZWFybkRGJG51bSA8LSBjKDE6bnJvdyhMZWFybkRGKSkKI9Ck0L7RgNC80YPRlNC80L4g0YDQvtCx0L7Rh9GDINGC0LDQsdC70LjRhtGOINC90LDQstGH0LDQu9GM0L3QvtGXINCy0LjQsdGW0YDQutC4LAoj0LLQutCw0LfRg9GU0LzQviwg0YnQviDQstC40LHRltGA0LrQsCDQv9C+0LLQuNC90L3QsCDQvNGW0YHRgtC40YLQuCDQv9C+IDEwMDAg0L7QsSfRlNC60YLRltCyINC60L7QttC90L7Qs9C+INC60LvQsNGB0YMKI9GC0LAg0L3QsNC/0L7QstC90Y7QstCw0YLQuNGB0Ywg0LfQsCDQvNC10YLQvtC00L7QvCAi0L/QvtCy0LXRgNC90LXQvdC+0LPQviDRiNCw0YDRgyIKc2V0LnNlZWQoMTIyMTApCkxlYXJuREYgJT4lIGdyb3VwX2J5KENsYXNzKSAlPiUKICBzYW1wbGVfbihzaXplID0gMTAwMCwgcmVwbGFjZSA9IFRSVUUpICU+JQogIHVuZ3JvdXAoQ2xhc3MpICU+JQogIG11dGF0ZShDbGFzcyA9IGZhY3RvcihDbGFzcykpIC0+IExlYXJuREYuc2FtcGxlCiPQpNC+0YDQvNGD0ZTQvNC+INGC0LXRgdGC0L7QstGDINCy0LjQsdGW0YDQutGDCkxlYXJuREYkU2FtcGxlIDwtIGlmZWxzZShMZWFybkRGJG51bSAlaW4lIExlYXJuREYuc2FtcGxlJG51bSwgIkxlYXJuIiwgIlRlc3QiKQpMZWFybkRGICU+JSBmaWx0ZXIoU2FtcGxlID09ICJUZXN0IikgJT4lIGRwbHlyOjpzZWxlY3QoLWMobnVtLCBTYW1wbGUpKSAtPiBMZWFybkRGLnRlc3QKI9Cf0YDQuNCx0LjRgNCw0ZTQvNC+INCx0ZbQu9GM0YjQtSDQvdC1INC/0L7RgtGA0ZbQsdC90LUg0L/QvtC70LUgbnVtINCyINGC0LDQsdC70LjRhtGWIExlYXJuREYuc2FtcGxlCkxlYXJuREYuc2FtcGxlICU+JSBkcGx5cjo6c2VsZWN0KC1jKG51bSwgU2FtcGxlKSkgLT4gTGVhcm5ERi5zYW1wbGUKYGBgCgpgYGB7cn0KI9CU0LjQstC40LzQvtGB0Ywg0LLRltC00YHQvtGC0L7QuiDQt9Cw0L/QuNGB0ZbQsiDRgyDQvdCw0LLRh9Cw0LvRjNC90ZbQuSDRgtCwINGC0LXRgdGC0L7QstGW0Lkg0LLQuNCx0ZbRgNC60LDRhQpyb3VuZCgxMDAgKiAobnJvdyhMZWFybkRGLnNhbXBsZSkvbnJvdyhMZWFybkRGKSksIDApCnJvdW5kKDEwMCAqIChucm93KExlYXJuREYudGVzdCkvbnJvdyhMZWFybkRGKSksIDApCiPQptGW0LvQutC+0Lwg0LvQvtCz0ZbRh9C90L4g0YLQtSwg0YnQviDRgyDQvdCw0YEg0LLQuNC50LTQtSDQsdGW0LvRjNGI0LUgMTAwINCy0ZbQtNGB0L7RgtC60ZbQsjog0LzQuCDRhNC+0YDQvNGD0LLQsNC70Lgg0L3QsNCy0YfQsNC70YzQvdGDINCy0LjQsdGW0YDQutGDINC3INC/0L7QstC10YDQvdC10L3QvdGP0Lwg0ZYg0LTQtdGP0LrRliDRgNGP0LTQutC4INCx0YPQu9C+INCy0LfRj9GC0L4g0L/QviDQtNC10LrRltC70YzQutCwINGA0LDQt9GW0LIKYGBgCgpgYGB7cn0KI9CX0LDQstCw0L3RgtCw0LbRg9GU0LzQviDQv9Cw0LrQtdGCIFJhbmRvbSBGb3Jlc3QKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmBgYAoKYGBge3J9CiPQl9Cw0L/Rg9GB0LrQsNGU0LzQviDQvNC+0LTQtdC70Y7QstCw0L3QvdGPINGC0LAg0LLQutCw0LfRg9GU0LzQviDRgNC+0LHQvtGH0ZYg0L/QsNGA0LDQvNC10YLRgNC4INC/0YDQvtGG0LXRgdGDINC80L7QtNC10LvRjtCy0LDQvdC90Y8Kc2V0LnNlZWQoMTIyMTApClJGX21vZGVsX3RtcCA8LSByYW5kb21Gb3Jlc3QoQ2xhc3Mgfi4sIGRhdGEgPSBMZWFybkRGLnNhbXBsZSwKICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGxhY2UgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNpemUgPSAyLAogICAgICAgICAgICAgICAgICAgICAgICAgaW1wb3J0YW5jZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBtdHJ5ID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgIG50cmVlID0gNTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgZG8udHJhY2UgPSAyMCkKYGBgCgpgYGB7cn0KI9CU0LjQstC40LzQvtGB0Ywg0YDQtdC30YPQu9GM0YLQsNGCINC80L7QtNC10LvRjtCy0LDQvdC90Y8KUkZfbW9kZWxfdG1wCmBgYAoKYGBge3J9CiPQktC40LrQvtC90YPRlNC80L4g0LrQu9Cw0YHQuNGE0ZbQutCw0YbRltGOINC00LvRjyDQstGB0ZbRlNGXINGC0LXRgNC40YLQvtGA0ZbRlyDQmtGA0LjQstC+0LPQviDQoNC+0LPRgyDRgtCwINGE0ZbQutGB0YPRlNC80L4g0YfQsNGBINCy0LjQutC+0L3QsNC90L3RjwpiZWdpbkNsdXN0ZXIoKQpzeXN0ZW0udGltZShHYXpvbl9SRl90bXAgPC0gY2x1c3RlclIoSW1hZ2VTdGFjaywgcmFzdGVyOjpwcmVkaWN0LCBhcmdzID0gbGlzdChtb2RlbCA9IFJGX21vZGVsX3RtcCkpKQplbmRDbHVzdGVyKCkKYGBgCgpgYGB7cn0KI9CU0LjQstC40LzQvtGB0Ywg0ZbQvdGE0L7RgNC80LDRhtGW0Y4g0YnQvtC00L4g0ZbQvdGE0L7RgNC80LDRgtC40LLQvdC+0YHRgtGWINC/0YDQtdC00LjQutGC0L7RgNGW0LIKdmFySW1wUGxvdChSRl9tb2RlbF90bXAsIHNvcnQgPSBUUlVFLCBtYWluID0gItCG0L3RhNC+0YDQvNCw0YLQuNCy0L3RltGB0YLRjCDQv9GA0LXQtNC40LrRgtC+0YDRltCyIikKYGBgCgpgYGB7cn0KI9CU0LjQstC40LzQvtGB0Ywg0ZbQvdGE0L7RgNC80LDRhtGW0Y4g0L/RgNC+INC60ZbQu9GM0LrRltGB0YLRjCDRgNC+0YHRidC10L/Qu9C10L3QvdGPINC00LXRgNC10LIg0L3QsCDQutC+0LbQvdC+0LzRgyDQtyDQv9GA0LXQtNC40LrRgtC+0YDRltCyCnZhclVzZWQoUkZfbW9kZWxfdG1wLCBieS50cmVlID0gRkFMU0UsIGNvdW50ID0gVFJVRSkKYGBgCgpgYGB7cn0KcGxvdChSRl9tb2RlbF90bXAsIGx3ZCA9IDIsIGNvbCA9IHJhaW5ib3coMTApKQpsZWdlbmQoInRvcHJpZ2h0IiwgY29sbmFtZXMoUkZfbW9kZWxfdG1wJGVyci5yYXRlKSwgY29sID0gcmFpbmJvdygxMCksIGNleCA9IDAuOCwgZmlsbCA9IHJhaW5ib3coMTApKQpgYGAKCmBgYHtyfQoj0JfQsNC/0LjRgdGD0ZTQvNC+INCy0ZbQtNC+0LrRgNC10LzQu9C10L3QuNC5INGA0LDRgdGC0YDQvtCy0LjQuSDRhNCw0LnQuyDQtyDRgNC10LfRg9C70YzRgtCw0YLQsNC80Lgg0LrQu9Cw0YHQuNGE0ZbQutCw0YbRltGXCndyaXRlUmFzdGVyKEdhem9uX1JGX3RtcCwgIi9ob21lL2dla2EvRG9jdW1lbnRzL1podXJuUm96c2xpZC9EYXRhU3RvcnkvRWNvbG9neS9VcmJhbi9HYXpvbjIwMTcwODA4L1dpdGhvdXREZWdMYXduL0dhem9uMjAxNzA4MDhfbm9EZWdMYXduX3RtcC5zZGF0IiwgZm9ybWF0ID0gIlNBR0EiLCBvdmVyd3JpdGUgPSBUUlVFKQpgYGAKCmBgYHtyfQoj0J/QtdGA0LXQstGW0YDRj9GU0LzQviDRgNC10LfRg9C70YzRgtCw0YIg0LrQu9Cw0YHQuNGE0ZbQutCw0YbRltGXINC90LAgItGC0LXRgdGC0L7QstGW0LkiINCy0LjQsdGW0YDRhtGWCkdhem9uX0RGLnByZWRpY3RfdG1wIDwtIHByZWRpY3QoUkZfbW9kZWxfdG1wLCBMZWFybkRGLnRlc3QpCnRhYmxlKEdhem9uX0RGLnByZWRpY3RfdG1wLCBMZWFybkRGLnRlc3QkQ2xhc3MpCiPQntCx0YfQuNGB0LvRjtGU0LzQviDQv9C+0YXQuNCx0LrRgyDQutC70LDRgdC40YTRltC60LDRhtGW0Zcg0L3QsCAi0YLQtdGB0YLQvtCy0ZbQuSIiINCy0LjQsdGW0YDRhtGWCnN1bShkaWFnKHRhYmxlKEdhem9uX0RGLnByZWRpY3RfdG1wLCBMZWFybkRGLnRlc3QkQ2xhc3MpKSkvc3VtKHRhYmxlKEdhem9uX0RGLnByZWRpY3RfdG1wLCBMZWFybkRGLnRlc3QkQ2xhc3MpKQoKIyEhIdGB0LvQvtCy0L4gItGC0LXRgdGC0L7QstCwIiDRjyDQvdCw0LLQvNC40YHQvdC+INCy0LfRj9CyINGDINC70LDQv9C60LguINCm0LUg0L3QtSDRh9C40YHRgtCwINGC0LXRgdGC0L7QstCwINCy0LjQsdGW0YDQutCwLiDQp9C10YDQtdC3INC80LDQu9GDINC60ZbQu9GM0LrRltGB0YLRjCDQvtCxJ9GU0LrRgtGW0LIg0LTQu9GPINC00LXRj9C60LjRhSDQutC70LDRgdGW0LIg0LzQuCDRiNGC0YPRh9C90L4g0LLQt9GP0LvQuCDRhtGWINC+0LEn0ZTQutGC0Lgg0L/QviAyLTMtNSDRgNCw0LfRltCyLiDQotC+0LzRgyDQudC80L7QstGW0YDQvdC+LCDRidC+INC00LvRjyDRhtGPINGG0LjRhSDQutC70LDRgdGW0LIg0YMgItGC0LXRgdGC0L7QstGW0LkiINCy0LjQsdGW0YDRhtGWINC90LUg0LfQsNC70LjRiNC40LvQvtGB0Ywg0YPQvdGW0LrQsNC70YzQvdC40YUg0L7QsSfRlNC60YLRltCyLiDQkCDQtNC70Y8g0LrQu9Cw0YHRgyBCdXJuZWQgQXJlYSDRgtC+0YfQvdC+INC90LUg0LfQsNC70LjRiNC40LvQvtGB0Ywg0YPQvdGW0LrQsNC70YzQvdC40YUg0L7QsSfRlNC60YLRltCyINGDINGC0LXRgdGC0L7QstGW0Lkg0LLQuNCx0ZbRgNGG0ZYKYGBgCgrQn9C+0LTQsNC70YzRiNCwINGA0L7QsdC+0YLQsCDQtyDQvtGC0YDQuNC80LDQvdC40Lwg0YTQsNC50LvQvtC8INC60LvQsNGB0LjRhNGW0LrQvtCy0LDQvdC40YUg0YLQuNC/0ZbQsiDRgtC10YDQuNGC0L7RgNGW0Zcg0LLQuNC60L7QvdGD0ZTRgtGM0YHRjyDQsiDRgdC10YDQtdC00L7QstC40YnRliDQs9C10L7RltC90YTQvtGA0LzQsNGG0ZbQudC90LjRhSDRgdC40YHRgtC10LwuINCX0L7QutGA0LXQvNCwLCDRjyDQstC40LrQvtGA0LjRgdGC0LDQsiDQsdCw0LfQvtCy0ZYg0LzQvtC20LvQuNCy0L7RgdGC0ZYg0JPQhtChIFNBR0Eg0LTQu9GPINC/0YDQvtCy0LXQtNC10L3QvdGPINC30LPQu9Cw0LTQttGD0LLQsNC70YzQvdC+0Zcg0YTRltC70YzRgtGA0LDRhtGW0Zcg0L7RgtGA0LjQvNCw0L3QvtCz0L4g0YDQsNGB0YLRgNGDINC60LvQsNGB0LjRhNGW0LrQsNGG0ZbRly4g0J/RgNC4INGG0YzQvtC80YMg0LHRg9C70L4g0YPRgdGD0L3QtdC90L4g0L7QtNC90L4t0LTQstC+0L/RltC60YHQtdC70YzQvdGWIOKAnNCw0YDRgtC10YTQsNC60YLQuOKAnS4g0JTQu9GPINC+0LHRh9C40YHQu9C10L3QvdGPINC/0LvQvtGJINGC0LAg0ZbQvdGI0L7RlyDQsdCw0LfQvtCy0L7RlyDRgdGC0LDRgtC40YHRgtC40LrQuCDRjyDRgtCw0LrQvtC2INCy0LjQutC+0YDQuNGB0YLQsNCyINCT0IbQoSBTQUdBLiDQlNC70Y8g4oCc0L/QvtC70ZbQs9GA0LDRhNGW0YfQvdC+0LPQvuKAnSDQvtGE0L7RgNC80LvQtdC90L3RjyDRgNC10LfRg9C70YzRgtCw0YLRltCyINGPINCy0LjQutC+0YDQuNGB0YLQvtCy0YPRjiDQsdCw0LfQvtCy0ZYg0LzQvtC20LvQuNCy0L7RgdGC0ZYg0JPQhtChIFFHSVMuCgrQodGC0L7RgdC+0LLQvdC+INC30LDQs9Cw0LvRjNC90L7RlyDRgtC+0YfQvdC+0YHRgtGWINC80L7QtNC10LvRljog0LIg0LfQsNCz0LDQu9GM0L3QuNGFINGA0LjRgdCw0YUg0LTQvtCy0L7Qu9GWINGC0L7Rh9C90L4g0L/QvtCy0YLQvtGA0Y7RlCDQvtGB0L7QsdC70LjQstC+0YHRgtGWINC80ZbRgdGM0LrQvtGXINGC0LXRgNC40YLQvtGA0ZbRlzog0YDQsNC50L7QvdC4INC/0YDQuNCy0LDRgtC90L7Qs9C+INGB0LXQutGC0L7RgNGDLCDQvtC60YDQtdC80ZYg0LLQuNGB0L7RgtC90ZYg0LHRg9C00LjQvdC60LgsINC30LDRgNC+0YHQu9GWINC+0YfQtdGA0LXRgtGW0LIuINCi0YDQsNC/0LvRj9GO0YLRjNGB0Y8g0L/QvtC+0LTQuNC90L7QutGWINC80ZbRgdGG0Y8sINGP0LrRliDQt9C90LDRhdC+0LTRj9GC0YzRgdGPINGDINC30LDRgtGW0L3QutGDINGP0Log0LTQu9GPINC+0L/RgtC40YfQvdC40YUg0ZYg0YDQsNC00LDRgNC90LjRhSDRgdGD0L/Rg9GC0L3QuNC60ZbQsiwg0YLQsNC6INGWINC00LvRjyDQodC+0L3RhtGPLiDQptGWINC80ZbRgdGG0Y8g0YfQsNGB0YLQviDRgNC+0LfQv9GW0LfQvdCw0Y7RgtGM0YHRjyDRj9C6IOKAnNCS0L7QtNCw4oCdLiDQntGB0L7QsdC70LjQstC+INGG0LUg0YHRgtC+0YHRg9GU0YLRjNGB0Y8g0YHRhdGW0LTQvdC40YUg0LHQvtGA0YLRltCyINC00LXRj9C60LjRhSDQstC10LvQuNC60LjRhSDQutGA0LjQstC+0YDRltC30YzQutC40YUg0LrQsNGA4oCZ0ZTRgNGW0LIuINCi0LDQutC+0LYg0YHQv9C+0YHRgtC10YDRltCz0LDRjtGC0YzRgdGPINC/0ZbQutGB0LXQu9GWINC60LvQsNGB0YMg4oCc0J7Rh9C10YDQtdGC0LjigJ0g0YMg0LfQvtCy0YHRltC8INC90LXRhdCw0YDQsNC60YLQtdGA0L3QuNGFINC80ZbRgdGG0Y/RhS4g0KHQutC+0YDRltGI0LUg0LfQsCDQstGB0LUg4oCUINGG0LUg0YnRltC70YzQvdCwINC60YPRgdGC0LDRgNC90LjQutC+0LLQsCDRgNC+0YHQu9C40L3QvdGW0YHRgtGMLiDQptC1INC/0L7RgtGA0LXQsdGD0ZQg0L/QtdGA0LXQstGW0YDQutC4INC90LAg0LzRltGB0YbQtdCy0L7RgdGC0ZYu