1. Результаты прогнозирования с использованием пакета prophet
# View first 20 rows of the forecasting result using prophet package on M3-competition data
# ds: timestamp
# yhat: forecasts
# yhat_lower: Lo 80
# yhat_upper: Hi 80
# yhat_lower95: Lo 95
# yhat_upper95: Hi 95
head(M3Prophet, 20)
Использование пакета pcbars для оценки этого результата
# View total data on each horizon
M3Prophet_total
Для forecast_within_80:
# Using pcbars package for M3Prophet_total data
# Input: A data frame containing columns: category, case and total
# For forecasts within 80%
category <- paste("Prophet_with_horizon =", unique(M3Prophet_total$horizon))
cases <- M3Prophet_total$forecast_within_80
total <- M3Prophet_total$total_forecast
df1 <- data.frame(category, cases, total)
estimatePercentageErrors(df1)

Для forecast_within_95
# Using pcbars package for M3Prophet_total data
# Input: A data frame containing columns: category, case and total
# For forecasts within 95%
category <- paste("Prophet_with_horizon =", unique(M3Prophet_total$horizon))
cases <- M3Prophet_total$forecast_within_95
total <- M3Prophet_total$total_forecast
df2 <- data.frame(category, cases, total)
estimatePercentageErrors(df2)

Анализ в разрезе типов рядов
# View the M3prophet_total_category
M3prophet_total_category
Для forecast_within_80:
# pcbars for M3prophet_total_category data
# input: A data frame containing columns category, case, total
# for forecasts within 80 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3prophet_total_category$category
cases <- M3prophet_total_category$forecast_within_80
total <- M3prophet_total_category$total_forecast
df3 <- data.frame(category, cases, total)
estimatePercentageErrors(df3)

Для forecast_within_95:
# pcbars for M3prophet_total_category data
# input: A data frame containing columns category, case, total
# for forecasts within 95 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3prophet_total_category$category
cases <- M3prophet_total_category$forecast_within_95
total <- M3prophet_total_category$total_forecast
df4 <- data.frame(category, cases, total)
estimatePercentageErrors(df4)

2. Результаты прогнозирования с использованием Arima и BoxCox преобразованием
# View first 20 rows of M3Arima_BoxCox data
head(M3Arima_BoxCox, 20)
набор данных, полученный с применением BoxCox и Arima имеет NAs (missing values) в колонках Hi80 and Hi95
# Check whether rows contain any NAs:
row.has.na <- apply(M3Arima_BoxCox, 1, function(x){any(is.na(x))})
sum(row.has.na)
[1] 5048
# Remove NAs values
df5 <- M3Arima_BoxCox[complete.cases(M3Arima_BoxCox), ]
Использование пакета pcbars для оценки этого результата после удаления строк с NAs values
# View M3Arima_total_BoxCox data
M3Arima_total_BoxCox
Для forecast_within_80:
# Using pcbars package for M3Arima_total_BoxCox data
# Input: A data frame containing columns: category, case and total
# For forecasts within 80%
category <- paste("Arima-Boxcox_with_horizon =", unique(M3Arima_total_BoxCox$horizon))
cases <- M3Arima_total_BoxCox$forecast_within_80
total <- M3Arima_total_BoxCox$total_forecast
df6 <- data.frame(category, cases, total)
estimatePercentageErrors(df6)

Для forecast_within_95:
# Using pcbars package for M3Arima_total_BoxCox data
# Input: A data frame containing columns: category, case and total
# For forecasts within 95%
category <- paste("Arima-Boxcox_with_horizon =", unique(M3Arima_total_BoxCox$horizon))
cases <- M3Arima_total_BoxCox$forecast_within_95
total <- M3Arima_total_BoxCox$total_forecast
df7 <- data.frame(category, cases, total)
estimatePercentageErrors(df7)

Анализ в разрезе типов рядов
# View the M3Arima_total_BoxCox_category data
M3Arima_total_BoxCox_category
Для forecast_within_80:
# pcbars for M3Arima_total_BoxCox_category data
# input: A data frame containing columns category, case, total
# for forecasts within 80 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3Arima_total_BoxCox_category$category
cases <- M3Arima_total_BoxCox_category$forecast_within_80
total <- M3Arima_total_BoxCox_category$total_forecast
df8 <- data.frame(category, cases, total)
estimatePercentageErrors(df8)

Для forecast_within_95:
# pcbars for M3Arima_total_BoxCox_category data
# input: A data frame containing columns category, case, total
# for forecasts within 95 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3Arima_total_BoxCox_category$category
cases <- M3Arima_total_BoxCox_category$forecast_within_95
total <- M3Arima_total_BoxCox_category$total_forecast
df9 <- data.frame(category, cases, total)
estimatePercentageErrors(df9)

3. Результаты прогнозирования с использованием Ets and BoxCox преобразования:
# View first 20 rows of M3Ets_BoxCox data
head(M3Ets_BoxCox, 20)
набор данных, полученный с применением ETS и BoxCox имеет NAs (missing values) в колонках Hi80 and Hi95
# Check whether rows contain any NAs:
row.has.na <- apply(M3Ets_BoxCox, 1, function(x){any(is.na(x))})
sum(row.has.na)
[1] 378
# Remove NAs values
df10<- M3Ets_BoxCox[complete.cases(M3Ets_BoxCox), ]
Использование пакета pcbars для оценки этого результата после удаления строк с NAs values
# View M3Arima_total_BoxCox data
M3Ets_total_BoxCox
Для forecast_within_80:
# Using pcbars package for M3Ets_total_BoxCox data
# Input: A data frame containing columns: category, case and total
# For forecasts within 80%
category <- paste("ETS-Boxcox_with_horizon =", unique(M3Ets_total_BoxCox$horizon))
cases <- M3Ets_total_BoxCox$forecast_within_80
total <- M3Ets_total_BoxCox$total_forecast
df11<- data.frame(category, cases, total)
estimatePercentageErrors(df11)

Для forecast_within_95:
# Using pcbars package for M3Ets_total_BoxCox data
# Input: A data frame containing columns: category, case and total
# For forecasts within 95%
category <- paste("ETS-Boxcox_with_horizon =", unique(M3Ets_total_BoxCox$horizon))
cases <- M3Ets_total_BoxCox$forecast_within_95
total <- M3Ets_total_BoxCox$total_forecast
df12<- data.frame(category, cases, total)
estimatePercentageErrors(df12)

Анализ в разрезе типов рядов
# View the M3prophet_total_category
M3Ets_total_BoxCox_category
Для forecast_within_80:
# pcbars for M3Ets_total_BoxCox_category data
# input: A data frame containing columns category, case, total
# for forecasts within 80 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3Ets_total_BoxCox_category$category
cases <- M3Ets_total_BoxCox_category$forecast_within_80
total <- M3Ets_total_BoxCox_category$total_forecast
df13<- data.frame(category, cases, total)
estimatePercentageErrors(df13)

Для forecast_within_95:
# pcbars for M3Ets_total_BoxCox_category data
# input: A data frame containing columns category, case, total
# for forecasts within 95 %
# conf. interval of estimatePercentageErrors by default: 95%
category <- M3Ets_total_BoxCox_category$category
cases <- M3Ets_total_BoxCox_category$forecast_within_95
total <- M3Ets_total_BoxCox_category$total_forecast
df14<- data.frame(category, cases, total)
estimatePercentageErrors(df14)

LS0tDQp0aXRsZTogIlByb3BoZXQgKyBCb3hDb3ggZm9yIGFyaW1hIGFuZCBldHMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KIyMjIyAxLiDQoNC10LfRg9C70YzRgtCw0YLRiyDQv9GA0L7Qs9C90L7Qt9C40YDQvtCy0LDQvdC40Y8g0YEg0LjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC40LXQvCDQv9Cw0LrQtdGC0LAgcHJvcGhldA0KDQoNCmBgYHtyfQ0KIyBWaWV3IGZpcnN0IDIwIHJvd3Mgb2YgdGhlIGZvcmVjYXN0aW5nIHJlc3VsdCB1c2luZyBwcm9waGV0IHBhY2thZ2Ugb24gTTMtY29tcGV0aXRpb24gZGF0YQ0KIyBkczogdGltZXN0YW1wDQojIHloYXQ6IGZvcmVjYXN0cw0KIyB5aGF0X2xvd2VyOiBMbyA4MA0KIyB5aGF0X3VwcGVyOiBIaSA4MA0KIyB5aGF0X2xvd2VyOTU6IExvIDk1DQojIHloYXRfdXBwZXI5NTogSGkgOTUNCmhlYWQoTTNQcm9waGV0LCAyMCkNCg0KYGBgDQoNCiMjIyMg0JjRgdC/0L7Qu9GM0LfQvtCy0LDQvdC40LUg0L/QsNC60LXRgtCwIHBjYmFycyDQtNC70Y8g0L7RhtC10L3QutC4INGN0YLQvtCz0L4g0YDQtdC30YPQu9GM0YLQsNGC0LANCg0KDQpgYGB7cn0NCiMgVmlldyB0b3RhbCBkYXRhIG9uIGVhY2ggaG9yaXpvbg0KTTNQcm9waGV0X3RvdGFsDQpgYGAgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fODA6DQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMn0NCiMgVXNpbmcgcGNiYXJzIHBhY2thZ2UgZm9yIE0zUHJvcGhldF90b3RhbCBkYXRhDQojIElucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zOiBjYXRlZ29yeSwgY2FzZSBhbmQgdG90YWwNCiMgRm9yIGZvcmVjYXN0cyB3aXRoaW4gODAlDQpjYXRlZ29yeSA8LSBwYXN0ZSgiUHJvcGhldF93aXRoX2hvcml6b24gPSIsIHVuaXF1ZShNM1Byb3BoZXRfdG90YWwkaG9yaXpvbikpDQpjYXNlcyA8LSBNM1Byb3BoZXRfdG90YWwkZm9yZWNhc3Rfd2l0aGluXzgwDQp0b3RhbCA8LSBNM1Byb3BoZXRfdG90YWwkdG90YWxfZm9yZWNhc3QNCmRmMSA8LSBkYXRhLmZyYW1lKGNhdGVnb3J5LCBjYXNlcywgdG90YWwpDQplc3RpbWF0ZVBlcmNlbnRhZ2VFcnJvcnMoZGYxKQ0KYGBgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fOTUNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBVc2luZyBwY2JhcnMgcGFja2FnZSBmb3IgTTNQcm9waGV0X3RvdGFsIGRhdGENCiMgSW5wdXQ6IEEgZGF0YSBmcmFtZSBjb250YWluaW5nIGNvbHVtbnM6IGNhdGVnb3J5LCBjYXNlIGFuZCB0b3RhbA0KIyBGb3IgZm9yZWNhc3RzIHdpdGhpbiA5NSUNCmNhdGVnb3J5IDwtIHBhc3RlKCJQcm9waGV0X3dpdGhfaG9yaXpvbiA9IiwgdW5pcXVlKE0zUHJvcGhldF90b3RhbCRob3Jpem9uKSkNCmNhc2VzIDwtIE0zUHJvcGhldF90b3RhbCRmb3JlY2FzdF93aXRoaW5fOTUNCnRvdGFsIDwtIE0zUHJvcGhldF90b3RhbCR0b3RhbF9mb3JlY2FzdA0KZGYyIDwtIGRhdGEuZnJhbWUoY2F0ZWdvcnksIGNhc2VzLCB0b3RhbCkNCmVzdGltYXRlUGVyY2VudGFnZUVycm9ycyhkZjIpDQpgYGANCg0KIyMjIyDQkNC90LDQu9C40Lcg0LIg0YDQsNC30YDQtdC30LUg0YLQuNC/0L7QsiDRgNGP0LTQvtCyDQoNCmBgYHtyfQ0KIyBWaWV3IHRoZSBNM3Byb3BoZXRfdG90YWxfY2F0ZWdvcnkNCk0zcHJvcGhldF90b3RhbF9jYXRlZ29yeQ0KYGBgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fODA6DQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMn0NCiMgcGNiYXJzIGZvciBNM3Byb3BoZXRfdG90YWxfY2F0ZWdvcnkgZGF0YQ0KIyBpbnB1dDogQSBkYXRhIGZyYW1lIGNvbnRhaW5pbmcgY29sdW1ucyBjYXRlZ29yeSwgY2FzZSwgdG90YWwNCiMgZm9yIGZvcmVjYXN0cyB3aXRoaW4gODAgJQ0KIyBjb25mLiBpbnRlcnZhbCBvZiBlc3RpbWF0ZVBlcmNlbnRhZ2VFcnJvcnMgYnkgZGVmYXVsdDogOTUlDQpjYXRlZ29yeSA8LSBNM3Byb3BoZXRfdG90YWxfY2F0ZWdvcnkkY2F0ZWdvcnkNCmNhc2VzIDwtIE0zcHJvcGhldF90b3RhbF9jYXRlZ29yeSRmb3JlY2FzdF93aXRoaW5fODANCnRvdGFsIDwtIE0zcHJvcGhldF90b3RhbF9jYXRlZ29yeSR0b3RhbF9mb3JlY2FzdA0KZGYzIDwtIGRhdGEuZnJhbWUoY2F0ZWdvcnksIGNhc2VzLCB0b3RhbCkNCmVzdGltYXRlUGVyY2VudGFnZUVycm9ycyhkZjMpDQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl85NToNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBwY2JhcnMgZm9yIE0zcHJvcGhldF90b3RhbF9jYXRlZ29yeSBkYXRhDQojIGlucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zIGNhdGVnb3J5LCBjYXNlLCB0b3RhbA0KIyBmb3IgZm9yZWNhc3RzIHdpdGhpbiA5NSAlDQojIGNvbmYuIGludGVydmFsIG9mIGVzdGltYXRlUGVyY2VudGFnZUVycm9ycyBieSBkZWZhdWx0OiA5NSUNCmNhdGVnb3J5IDwtIE0zcHJvcGhldF90b3RhbF9jYXRlZ29yeSRjYXRlZ29yeQ0KY2FzZXMgPC0gTTNwcm9waGV0X3RvdGFsX2NhdGVnb3J5JGZvcmVjYXN0X3dpdGhpbl85NQ0KdG90YWwgPC0gTTNwcm9waGV0X3RvdGFsX2NhdGVnb3J5JHRvdGFsX2ZvcmVjYXN0DQpkZjQgPC0gZGF0YS5mcmFtZShjYXRlZ29yeSwgY2FzZXMsIHRvdGFsKQ0KZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzKGRmNCkNCmBgYA0KDQojIyMjIDIuINCg0LXQt9GD0LvRjNGC0LDRgtGLINC/0YDQvtCz0L3QvtC30LjRgNC+0LLQsNC90LjRjyDRgSDQuNGB0L/QvtC70YzQt9C+0LLQsNC90LjQtdC8IEFyaW1hINC4IEJveENveCDQv9GA0LXQvtCx0YDQsNC30L7QstCw0L3QuNC10LwNCg0KYGBge3J9DQojIFZpZXcgZmlyc3QgMjAgcm93cyBvZiBNM0FyaW1hX0JveENveCBkYXRhDQpoZWFkKE0zQXJpbWFfQm94Q294LCAyMCkNCmBgYA0KDQojIyMjINC90LDQsdC+0YAg0LTQsNC90L3Ri9GFLCDQv9C+0LvRg9GH0LXQvdC90YvQuSDRgSDQv9GA0LjQvNC10L3QtdC90LjQtdC8IEJveENveCDQuCBBcmltYSDQuNC80LXQtdGCIE5BcyAobWlzc2luZyB2YWx1ZXMpINCyINC60L7Qu9C+0L3QutCw0YUgSGk4MCBhbmQgSGk5NQ0KDQpgYGB7cn0NCiMgQ2hlY2sgd2hldGhlciByb3dzIGNvbnRhaW4gYW55IE5BczoNCnJvdy5oYXMubmEgPC0gYXBwbHkoTTNBcmltYV9Cb3hDb3gsIDEsIGZ1bmN0aW9uKHgpe2FueShpcy5uYSh4KSl9KQ0Kc3VtKHJvdy5oYXMubmEpDQojIFJlbW92ZSBOQXMgdmFsdWVzDQpkZjUgPC0gTTNBcmltYV9Cb3hDb3hbY29tcGxldGUuY2FzZXMoTTNBcmltYV9Cb3hDb3gpLCBdDQpgYGANCg0KIyMjIyDQmNGB0L/QvtC70YzQt9C+0LLQsNC90LjQtSDQv9Cw0LrQtdGC0LAgcGNiYXJzINC00LvRjyDQvtGG0LXQvdC60Lgg0Y3RgtC+0LPQviDRgNC10LfRg9C70YzRgtCw0YLQsCDQv9C+0YHQu9C1INGD0LTQsNC70LXQvdC40Y8g0YHRgtGA0L7QuiDRgSBOQXMgdmFsdWVzDQoNCmBgYHtyfQ0KIyBWaWV3IE0zQXJpbWFfdG90YWxfQm94Q294IGRhdGEgDQpNM0FyaW1hX3RvdGFsX0JveENveA0KDQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl84MDoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBVc2luZyBwY2JhcnMgcGFja2FnZSBmb3IgTTNBcmltYV90b3RhbF9Cb3hDb3ggZGF0YQ0KIyBJbnB1dDogQSBkYXRhIGZyYW1lIGNvbnRhaW5pbmcgY29sdW1uczogY2F0ZWdvcnksIGNhc2UgYW5kIHRvdGFsDQojIEZvciBmb3JlY2FzdHMgd2l0aGluIDgwJQ0KY2F0ZWdvcnkgPC0gcGFzdGUoIkFyaW1hLUJveGNveF93aXRoX2hvcml6b24gPSIsIHVuaXF1ZShNM0FyaW1hX3RvdGFsX0JveENveCRob3Jpem9uKSkNCmNhc2VzIDwtIE0zQXJpbWFfdG90YWxfQm94Q294JGZvcmVjYXN0X3dpdGhpbl84MA0KdG90YWwgPC0gTTNBcmltYV90b3RhbF9Cb3hDb3gkdG90YWxfZm9yZWNhc3QNCmRmNiA8LSBkYXRhLmZyYW1lKGNhdGVnb3J5LCBjYXNlcywgdG90YWwpDQplc3RpbWF0ZVBlcmNlbnRhZ2VFcnJvcnMoZGY2KQ0KYGBgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fOTU6DQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMn0NCiMgVXNpbmcgcGNiYXJzIHBhY2thZ2UgZm9yIE0zQXJpbWFfdG90YWxfQm94Q294IGRhdGENCiMgSW5wdXQ6IEEgZGF0YSBmcmFtZSBjb250YWluaW5nIGNvbHVtbnM6IGNhdGVnb3J5LCBjYXNlIGFuZCB0b3RhbA0KIyBGb3IgZm9yZWNhc3RzIHdpdGhpbiA5NSUNCmNhdGVnb3J5IDwtIHBhc3RlKCJBcmltYS1Cb3hjb3hfd2l0aF9ob3Jpem9uID0iLCB1bmlxdWUoTTNBcmltYV90b3RhbF9Cb3hDb3gkaG9yaXpvbikpDQpjYXNlcyA8LSBNM0FyaW1hX3RvdGFsX0JveENveCRmb3JlY2FzdF93aXRoaW5fOTUNCnRvdGFsIDwtIE0zQXJpbWFfdG90YWxfQm94Q294JHRvdGFsX2ZvcmVjYXN0DQpkZjcgPC0gZGF0YS5mcmFtZShjYXRlZ29yeSwgY2FzZXMsIHRvdGFsKQ0KZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzKGRmNykNCmBgYA0KDQojIyMjINCQ0L3QsNC70LjQtyDQsiDRgNCw0LfRgNC10LfQtSDRgtC40L/QvtCyINGA0Y/QtNC+0LINCg0KYGBge3J9DQojIFZpZXcgdGhlIE0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5IGRhdGENCk0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5DQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl84MDoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBwY2JhcnMgZm9yIE0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5IGRhdGENCiMgaW5wdXQ6IEEgZGF0YSBmcmFtZSBjb250YWluaW5nIGNvbHVtbnMgY2F0ZWdvcnksIGNhc2UsIHRvdGFsDQojIGZvciBmb3JlY2FzdHMgd2l0aGluIDgwICUNCiMgY29uZi4gaW50ZXJ2YWwgb2YgZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzIGJ5IGRlZmF1bHQ6IDk1JQ0KY2F0ZWdvcnkgPC0gTTNBcmltYV90b3RhbF9Cb3hDb3hfY2F0ZWdvcnkkY2F0ZWdvcnkNCmNhc2VzIDwtIE0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5JGZvcmVjYXN0X3dpdGhpbl84MA0KdG90YWwgPC0gTTNBcmltYV90b3RhbF9Cb3hDb3hfY2F0ZWdvcnkkdG90YWxfZm9yZWNhc3QNCmRmOCA8LSBkYXRhLmZyYW1lKGNhdGVnb3J5LCBjYXNlcywgdG90YWwpDQplc3RpbWF0ZVBlcmNlbnRhZ2VFcnJvcnMoZGY4KQ0KYGBgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fOTU6DQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMn0NCiMgcGNiYXJzIGZvciBNM0FyaW1hX3RvdGFsX0JveENveF9jYXRlZ29yeSBkYXRhDQojIGlucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zIGNhdGVnb3J5LCBjYXNlLCB0b3RhbA0KIyBmb3IgZm9yZWNhc3RzIHdpdGhpbiA5NSAlDQojIGNvbmYuIGludGVydmFsIG9mIGVzdGltYXRlUGVyY2VudGFnZUVycm9ycyBieSBkZWZhdWx0OiA5NSUNCmNhdGVnb3J5IDwtIE0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5JGNhdGVnb3J5DQpjYXNlcyA8LSBNM0FyaW1hX3RvdGFsX0JveENveF9jYXRlZ29yeSRmb3JlY2FzdF93aXRoaW5fOTUNCnRvdGFsIDwtIE0zQXJpbWFfdG90YWxfQm94Q294X2NhdGVnb3J5JHRvdGFsX2ZvcmVjYXN0DQpkZjkgPC0gZGF0YS5mcmFtZShjYXRlZ29yeSwgY2FzZXMsIHRvdGFsKQ0KZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzKGRmOSkNCmBgYA0KDQojIyMjIDMuINCg0LXQt9GD0LvRjNGC0LDRgtGLINC/0YDQvtCz0L3QvtC30LjRgNC+0LLQsNC90LjRjyDRgSDQuNGB0L/QvtC70YzQt9C+0LLQsNC90LjQtdC8IEV0cyBhbmQgQm94Q294INC/0YDQtdC+0LHRgNCw0LfQvtCy0LDQvdC40Y86DQoNCmBgYHtyfQ0KIyBWaWV3IGZpcnN0IDIwIHJvd3Mgb2YgTTNFdHNfQm94Q294IGRhdGENCmhlYWQoTTNFdHNfQm94Q294LCAyMCkNCmBgYA0KDQojIyMjINC90LDQsdC+0YAg0LTQsNC90L3Ri9GFLCDQv9C+0LvRg9GH0LXQvdC90YvQuSDRgSDQv9GA0LjQvNC10L3QtdC90LjQtdC8ICBFVFMg0LggQm94Q294INC40LzQtdC10YIgTkFzIChtaXNzaW5nIHZhbHVlcykg0LIg0LrQvtC70L7QvdC60LDRhSBIaTgwIGFuZCBIaTk1DQoNCmBgYHtyfQ0KIyBDaGVjayB3aGV0aGVyIHJvd3MgY29udGFpbiBhbnkgTkFzOg0Kcm93Lmhhcy5uYSA8LSBhcHBseShNM0V0c19Cb3hDb3gsIDEsIGZ1bmN0aW9uKHgpe2FueShpcy5uYSh4KSl9KQ0Kc3VtKHJvdy5oYXMubmEpDQojIFJlbW92ZSBOQXMgdmFsdWVzDQpkZjEwPC0gTTNFdHNfQm94Q294W2NvbXBsZXRlLmNhc2VzKE0zRXRzX0JveENveCksIF0NCmBgYA0KDQojIyMjINCY0YHQv9C+0LvRjNC30L7QstCw0L3QuNC1INC/0LDQutC10YLQsCBwY2JhcnMg0LTQu9GPINC+0YbQtdC90LrQuCDRjdGC0L7Qs9C+INGA0LXQt9GD0LvRjNGC0LDRgtCwINC/0L7RgdC70LUg0YPQtNCw0LvQtdC90LjRjyDRgdGC0YDQvtC6INGBIE5BcyB2YWx1ZXMNCg0KYGBge3J9DQojIFZpZXcgTTNBcmltYV90b3RhbF9Cb3hDb3ggZGF0YSANCk0zRXRzX3RvdGFsX0JveENveA0KDQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl84MDoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBVc2luZyBwY2JhcnMgcGFja2FnZSBmb3IgTTNFdHNfdG90YWxfQm94Q294IGRhdGENCiMgSW5wdXQ6IEEgZGF0YSBmcmFtZSBjb250YWluaW5nIGNvbHVtbnM6IGNhdGVnb3J5LCBjYXNlIGFuZCB0b3RhbA0KIyBGb3IgZm9yZWNhc3RzIHdpdGhpbiA4MCUNCmNhdGVnb3J5IDwtIHBhc3RlKCJFVFMtQm94Y294X3dpdGhfaG9yaXpvbiA9IiwgdW5pcXVlKE0zRXRzX3RvdGFsX0JveENveCRob3Jpem9uKSkNCmNhc2VzIDwtIE0zRXRzX3RvdGFsX0JveENveCRmb3JlY2FzdF93aXRoaW5fODANCnRvdGFsIDwtIE0zRXRzX3RvdGFsX0JveENveCR0b3RhbF9mb3JlY2FzdA0KZGYxMTwtIGRhdGEuZnJhbWUoY2F0ZWdvcnksIGNhc2VzLCB0b3RhbCkNCmVzdGltYXRlUGVyY2VudGFnZUVycm9ycyhkZjExKQ0KYGBgDQoNCiMjIyMjINCU0LvRjyBmb3JlY2FzdF93aXRoaW5fOTU6DQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD0xMn0NCiMgVXNpbmcgcGNiYXJzIHBhY2thZ2UgZm9yIE0zRXRzX3RvdGFsX0JveENveCBkYXRhDQojIElucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zOiBjYXRlZ29yeSwgY2FzZSBhbmQgdG90YWwNCiMgRm9yIGZvcmVjYXN0cyB3aXRoaW4gOTUlDQpjYXRlZ29yeSA8LSBwYXN0ZSgiRVRTLUJveGNveF93aXRoX2hvcml6b24gPSIsIHVuaXF1ZShNM0V0c190b3RhbF9Cb3hDb3gkaG9yaXpvbikpDQpjYXNlcyA8LSBNM0V0c190b3RhbF9Cb3hDb3gkZm9yZWNhc3Rfd2l0aGluXzk1DQp0b3RhbCA8LSBNM0V0c190b3RhbF9Cb3hDb3gkdG90YWxfZm9yZWNhc3QNCmRmMTI8LSBkYXRhLmZyYW1lKGNhdGVnb3J5LCBjYXNlcywgdG90YWwpDQplc3RpbWF0ZVBlcmNlbnRhZ2VFcnJvcnMoZGYxMikNCmBgYA0KDQojIyMjINCQ0L3QsNC70LjQtyDQsiDRgNCw0LfRgNC10LfQtSDRgtC40L/QvtCyINGA0Y/QtNC+0LINCg0KYGBge3J9DQojIFZpZXcgdGhlIE0zcHJvcGhldF90b3RhbF9jYXRlZ29yeQ0KTTNFdHNfdG90YWxfQm94Q294X2NhdGVnb3J5DQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl84MDoNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBwY2JhcnMgZm9yIE0zRXRzX3RvdGFsX0JveENveF9jYXRlZ29yeSBkYXRhDQojIGlucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zIGNhdGVnb3J5LCBjYXNlLCB0b3RhbA0KIyBmb3IgZm9yZWNhc3RzIHdpdGhpbiA4MCAlDQojIGNvbmYuIGludGVydmFsIG9mIGVzdGltYXRlUGVyY2VudGFnZUVycm9ycyBieSBkZWZhdWx0OiA5NSUNCmNhdGVnb3J5IDwtIE0zRXRzX3RvdGFsX0JveENveF9jYXRlZ29yeSRjYXRlZ29yeQ0KY2FzZXMgPC0gTTNFdHNfdG90YWxfQm94Q294X2NhdGVnb3J5JGZvcmVjYXN0X3dpdGhpbl84MA0KdG90YWwgPC0gTTNFdHNfdG90YWxfQm94Q294X2NhdGVnb3J5JHRvdGFsX2ZvcmVjYXN0DQpkZjEzPC0gZGF0YS5mcmFtZShjYXRlZ29yeSwgY2FzZXMsIHRvdGFsKQ0KZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzKGRmMTMpDQpgYGANCg0KIyMjIyMg0JTQu9GPIGZvcmVjYXN0X3dpdGhpbl85NToNCg0KYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTEyfQ0KIyBwY2JhcnMgZm9yIE0zRXRzX3RvdGFsX0JveENveF9jYXRlZ29yeSBkYXRhDQojIGlucHV0OiBBIGRhdGEgZnJhbWUgY29udGFpbmluZyBjb2x1bW5zIGNhdGVnb3J5LCBjYXNlLCB0b3RhbA0KIyBmb3IgZm9yZWNhc3RzIHdpdGhpbiA5NSAlDQojIGNvbmYuIGludGVydmFsIG9mIGVzdGltYXRlUGVyY2VudGFnZUVycm9ycyBieSBkZWZhdWx0OiA5NSUNCmNhdGVnb3J5IDwtIE0zRXRzX3RvdGFsX0JveENveF9jYXRlZ29yeSRjYXRlZ29yeQ0KY2FzZXMgPC0gTTNFdHNfdG90YWxfQm94Q294X2NhdGVnb3J5JGZvcmVjYXN0X3dpdGhpbl85NQ0KdG90YWwgPC0gTTNFdHNfdG90YWxfQm94Q294X2NhdGVnb3J5JHRvdGFsX2ZvcmVjYXN0DQpkZjE0PC0gZGF0YS5mcmFtZShjYXRlZ29yeSwgY2FzZXMsIHRvdGFsKQ0KZXN0aW1hdGVQZXJjZW50YWdlRXJyb3JzKGRmMTQpDQpgYGA=