Motivations
Trong báo cáo có tên ĐÁNH GIÁ TÁC ĐỘNG CỦA COVID-19 ĐẾN NỀN KINH TẾ VÀ CÁC KHUYẾN NGHỊ CHÍNH SÁCH tại trang 10 có sử dụng mô hình SIR (tên đầy đủ là Susceptibles-Infectious-Recovered (SIR) epidemic model) đưa ra con số dự báo tương ứng với ba kịch bản khác nhau và ảnh hưởng tương ứng đối với nền kinh tế. Mô hình này có một tham số quan trọng là hệ số đặc trưng cho mức độ lây lan của dịch bệnh Ro. Mức độ quan trọng như vậy nên nó có hẳn cả một note để giải thích chi tiết ở đây và các kịch bản khác nhau (về số người sẽ bị nhiễm trong tương lai) thường được ước lượng và tính toán dựa trên các kịch bản khác nhau của hệ số Ro này (trong các tài liệu khác nhau, hệ số này có thể được kí hiệu khác nhau nhưng về ý nghĩa thì vẫn không có gì thay đổi) chứ không phải là các kịch bản từ khoảng thời gian t1 đến t2 nào đó.
Tuy vậy các tác giả lại không đề cập hay mô tả gì về việc hệ số này được ước lượng / tính toán như thế nào, hay là hệ số này được đưa vào SIR bằng phương pháp chuyên gia - tức là tham vấn các chuyên gia làm trong lĩnh vực Dịch Tễ Học về giá trị Ro nên được sử dụng cho SIR?
About SIR
SIR là một mô hình toán được biểu diễn bằng một hệ phương trình vi phân sử dụng để mô hình hóa mức độ lây lan của một dịch bệnh. Theo cách tiếp cận của mô hình này thì tốc độ lây lan của dịch bệnh được đo lường bằng ba thước đo là:
- Số người vẫn chưa bị nhiếm (Susceptible) và không được miễn dịch (và do đó có nguy cơ bị nhiễm bệnh).
- Số người bị nhiếm (Infected) và họ có khả năng lây nhiễm (Infectious).
- Số người hồi phục (Recovered). Một số tài liệu thì còn gọi là số người bị gạt bỏ (Removed) ra khỏi population có tiềm năng gây nhiễm bệnh vì vật chủ bị chết và do vậy không còn khả năng lây lan bệnh.
Về cơ bản mô hình này có một giả thuyết (trong số nhiều giả thuyết) rằng tốc độ lây lan của bệnh phụ thuộc vào một hệ số gọi là hệ số lây nhiễm Ro (trong khi cố định các yếu tố khác). Nếu hệ số này mà lớn thì số người bị nhiễm sẽ mau chóng đạt một cái đỉnh nào đó rồi giảm nhanh chóng (vì vật chủ bị nhiễm bệnh đã chết cả nên tốc độ lây lan sẽ giảm) và do vậy cách kịch bản khác nhau của dịch bệnh thì sẽ được phân tích và đánh giá dựa vào các kịch bản khác nhau của Ro. Đương nhiên hiểu biết về hệ số Ro này là lĩnh vực chuyên môn sâu của những người làm trong lĩnh vực Dịch Tễ Học.
SIR Modeling in R
Giả sử chúng ta muốn đánh giá mức độ lây lan của một loại bệnh dịch nào đó bằng mô hình SIR trong 90 ngày tới với các điều kiện ban đầu (Initial Conditions) như sau:
- Tại thời điểm ban đầu to có 10 người bị nhiễm bệnh và những người này có khả năng lây truyền bệnh cho các cá thể khác (vì không được cách li chẳng hạn).
- Tổng dân số trong cộng đồng là 100 (chú ý rằng tại mọi thời điểm thì S + I + R = Total Population = 100).
R có khá nhiều thư viện có thể sử dụng để thực hiện SIR (trong đó có thư viện EpiModel). Tuy nhiên trong post này chúng ta sẽ thực hiện SIR hơi tay chân một tí để hiểu việc triển khai từ mô hình toán đến R codes cho mô hình SIR của James Holland Jones với một số hiệu chỉnh:
# Load some packages:
library(tidyverse)
library(lubridate)
library(deSolve)
# Clear workspace:
rm(list = ls())
# Set some fixed paramters for SIR modeling:
times <- seq(0, 90, 1)
y0 <- c(90, 10, 0)
# Function calculates S, I and R:
sir <- function(t, y, p) {
yd1 <- -p["ho"]*y[1]*y[2]
yd2 <- p["ho"]*y[1]*y[2] - p["nu"]*y[2]
yd3 <- p["nu"]*y[2]
list(c(yd1, yd2, yd3), c(N = sum(y)))
}
# When ho = 0.001 (scenario 1):
pars1 <- c("ho" = 0.001, "nu" = 0.05)
sir.out1 <- lsoda(y0, times, sir, pars1)
data.frame(sir.out1) -> sir.out_df1
names(sir.out_df1) <- c("Time", "Susceptible", "Infected", "Recovered", "N")
sir.out_df1 %>%
mutate(Time = Time + date(now())) -> sir.out_df1
# When ho = 0.005 (scenario 2):
pars2 <- c("ho" = 0.005, "nu" = 0.05)
sir.out2 <- lsoda(y0, times, sir, pars2)
data.frame(sir.out2) -> sir.out_df2
names(sir.out_df2) <- c("Time", "Susceptible", "Infected", "Recovered", "N")
sir.out_df2 %>%
mutate(Time = Time + date(now())) -> sir.out_df2
# Plot:
library(hrbrthemes)
point1 <- sir.out_df1 %>% slice(which.max(Infected))
point2 <- sir.out_df2 %>% slice(which.max(Infected))
sir.out_df2 %>%
select(-N) %>%
gather(Type, Value, -Time) %>%
ggplot((aes(Time, Value, color = Type))) +
geom_line(size = 1) +
theme_modern_rc() +
labs(title = "Figure 1: Infected Cases predicted, SIR Approach", x = NULL, y = "Number of Cases") +
theme(axis.title.y = element_text(color = "white", size = 12)) +
scale_color_manual(values = c("cyan", "orange", "purple"), name = "") +
theme(legend.position = c(0.7, 0.5))

So sánh, ví dụ, mức độ lây lan của bệnh dịch căn cứ theo thước đo số người bị nhiếm tương ứng với hai kịch bản khác nhau của mức độ lây nhiễm trong khi cố định các tham số khác:
ggplot() +
geom_line(data = sir.out_df1, aes(Time, Infected, color = "Scenario 1"), size = 1) +
geom_point(data = point1, aes(Time, Infected, color = "Scenario 1"), size = 3) +
geom_line(data = sir.out_df2, aes(Time, Infected, color = "Scenario 2"), size = 1) +
geom_point(data = point2, aes(Time, Infected, color = "Scenario 2"), size = 3) +
theme_modern_rc() +
scale_y_continuous(limits = c(0, 70), breaks = seq(0, 70, 10)) +
scale_color_manual(values = c("cyan", "orange"), name = "") +
labs(title = "Figure 2: Infected Cases by Scenario, SIR Approach", x = NULL, y = "Infected Cases") +
theme(axis.title.y = element_text(color = "white", size = 12)) +
theme(legend.position = c(0.7, 0.5))

Figure 2 chỉ ra rằng với kịch bản 2 (có hệ số lây nhiễm 0.005) thì sẽ nhanh chóng đạt đến số người bị nhiễm bệnh cực đại (điểm màu vàng) sau đó giảm nhanh chóng. Nếu hệ số lây nhiễm giảm đi 5 lần thì số người nhiễm đạt cực đại thấp hơn chừng 3.4 lần (điểm màu xanh) nhưng sau đó thì số người nhiễm sẽ giảm chậm hơn so với kịch bản 1 (căn cứ vào độ dốc). Cái này cũng dễ hiểu vì nếu một dịch bệnh mà lây lan nhanh thì ngay sau khi đạt đỉnh, số người nhiễm sẽ giảm không phanh, thậm chí có thể tụt ngay về zero. Vì vật chủ nhiễm bệnh đã chết hết cả (Removed) hoặc đạt trạng thái được miễn dịch (Immunity): một bệnh dịch cụ thể thì nếu một người bị nhiễm nhưng sống sót thì sẽ không bao giờ mắc lại bệnh đó nữa.
LS0tDQp0aXRsZTogJ1NJUiBhcHByb2FjaCBmb3IgdW5kZXJzdGFuZGluZyBDb3JvbmF2aXJ1cyBwYW5kZW1pYycNCmF1dGhvcjogJ0F1dGhvcjogTmd1eWVuIENoaSBEdW5nJw0Kc3VidGl0bGU6ICJSIGZvciBGdW4iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAjIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSA2KQ0KYGBgDQoNCg0KIyBNb3RpdmF0aW9ucw0KDQpUcm9uZyBiw6FvIGPDoW8gY8OzIHTDqm4gW8SQw4FOSCBHScOBIFTDgUMgxJDhu5hORyBD4bumQSBDT1ZJRC0xOSDEkOG6vk4gTuG7gE4gS0lOSCBU4bq+IFbDgCBDw4FDIEtIVVnhur5OIE5HSOG7iiBDSMONTkggU8OBQ0hdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS9maWxlL2QvMUVoYU9lc3g4b3QtZzhzWlMyNG03RklKNWl2SGRQYnVxL3ZpZXc/ZmJjbGlkPUl3QVIwNGZ5cWlWV1VnWktKQ0YyOTFCeHBsd050ZnFSM1I3bndBejNVdm9nOVBESXBLdWpGM3p2TVBBNzQpIHThuqFpIHRyYW5nIDEwIGPDsyBz4butIGThu6VuZyBtw7QgaMOsbmggU0lSICh0w6puIMSR4bqneSDEkeG7pyBsw6AgU3VzY2VwdGlibGVzLUluZmVjdGlvdXMtUmVjb3ZlcmVkIChTSVIpIGVwaWRlbWljIG1vZGVsKSDEkcawYSByYSBjb24gc+G7kSBk4buxIGLDoW8gdMawxqFuZyDhu6luZyB24bubaSBiYSBr4buLY2ggYuG6o24ga2jDoWMgbmhhdSB2w6Ag4bqjbmggaMaw4bufbmcgdMawxqFuZyDhu6luZyDEkeG7kWkgduG7m2kgbuG7gW4ga2luaCB04bq/LiBNw7QgaMOsbmggIG7DoHkgY8OzIG3hu5l0IHRoYW0gc+G7kSBxdWFuIHRy4buNbmcgbMOgIGjhu4cgc+G7kSDEkeG6t2MgdHLGsG5nIGNobyBt4bupYyDEkeG7mSBsw6J5IGxhbiBj4bunYSBk4buLY2ggYuG7h25oIFJvLiBN4bupYyDEkeG7mSBxdWFuIHRy4buNbmcgbmjGsCB24bqteSBuw6puIG7DsyBjw7MgaOG6s24gY+G6oyBt4buZdCBub3RlIMSR4buDIGdp4bqjaSB0aMOtY2ggY2hpIHRp4bq/dCBb4bufIMSRw6J5XShodHRwczovL3dlYi5zdGFuZm9yZC5lZHUvfmpoajEvdGVhY2hpbmdkb2NzL0pvbmVzLW9uLVIwLnBkZikgdsOgIGPDoWMga+G7i2NoIGLhuqNuIGtow6FjIG5oYXUgKHbhu4Egc+G7kSBuZ8aw4budaSBz4bq9IGLhu4sgbmhp4buFbSB0cm9uZyB0xrDGoW5nIGxhaSkgdGjGsOG7nW5nIMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyB2w6AgdMOtbmggdG/DoW4gZOG7sWEgdHLDqm4gY8OhYyBr4buLY2ggYuG6o24ga2jDoWMgbmhhdSBj4bunYSBo4buHIHPhu5EgUm8gbsOgeSAodHJvbmcgY8OhYyB0w6BpIGxp4buHdSBraMOhYyBuaGF1LCBo4buHIHPhu5EgbsOgeSBjw7MgdGjhu4MgxJHGsOG7o2Mga8OtIGhp4buHdSBraMOhYyBuaGF1IG5oxrBuZyB24buBIMO9IG5naMSpYSB0aMOsIHbhuqtuIGtow7RuZyBjw7MgZ8OsIHRoYXkgxJHhu5VpKSBjaOG7qSBraMO0bmcgcGjhuqNpIGzDoCBjw6FjIGvhu4tjaCBi4bqjbiB04burIGtob+G6o25nIHRo4budaSBnaWFuIHQxIMSR4bq/biB0MiBuw6BvIMSRw7MuIA0KDQoNClR1eSB24bqteSBjw6FjIHTDoWMgZ2nhuqMgbOG6oWkga2jDtG5nIMSR4buBIGPhuq1wIGhheSBtw7QgdOG6oyBnw6wgduG7gSB2aeG7h2MgaOG7hyBz4buRIG7DoHkgxJHGsOG7o2MgxrDhu5tjIGzGsOG7o25nIC8gdMOtbmggdG/DoW4gbmjGsCB0aOG6vyBuw6BvLCBoYXkgbMOgIGjhu4cgc+G7kSBuw6B5IMSRxrDhu6NjIMSRxrBhIHbDoG8gU0lSIGLhurFuZyBwaMawxqFuZyBwaMOhcCBjaHV5w6puIGdpYSAtIHThu6ljIGzDoCB0aGFtIHbhuqVuIGPDoWMgY2h1ecOqbiBnaWEgbMOgbSB0cm9uZyBsxKluaCB24buxYyBE4buLY2ggVOG7hSBI4buNYyB24buBIGdpw6EgdHLhu4sgUm8gbsOqbiDEkcaw4bujYyBz4butIGThu6VuZyBjaG8gU0lSPyANCg0KIyBBYm91dCBTSVINCg0KU0lSIGzDoCBt4buZdCBtw7QgaMOsbmggdG/DoW4gxJHGsOG7o2MgYmnhu4N1IGRp4buFbiBi4bqxbmcgbeG7mXQgaOG7hyBwaMawxqFuZyB0csOsbmggdmkgcGjDom4gc+G7rSBk4bulbmcgxJHhu4MgbcO0IGjDrG5oIGjDs2EgbeG7qWMgxJHhu5kgbMOieSBsYW4gY+G7p2EgbeG7mXQgZOG7i2NoIGLhu4duaC4gVGhlbyBjw6FjaCB0aeG6v3AgY+G6rW4gY+G7p2EgbcO0IGjDrG5oIG7DoHkgdGjDrCB04buRYyDEkeG7mSBsw6J5IGxhbiBj4bunYSBk4buLY2ggYuG7h25oIMSRxrDhu6NjIMSRbyBsxrDhu51uZyBi4bqxbmcgYmEgdGjGsOG7m2MgxJFvIGzDoDogDQoNCi0gU+G7kSBuZ8aw4budaSB24bqrbiBjaMawYSBi4buLIG5oaeG6v20gKFN1c2NlcHRpYmxlKSB2w6Aga2jDtG5nIMSRxrDhu6NjIG1p4buFbiBk4buLY2ggKHbDoCBkbyDEkcOzIGPDsyBuZ3V5IGPGoSBi4buLIG5oaeG7hW0gYuG7h25oKS4gDQotIFPhu5EgbmfGsOG7nWkgYuG7iyBuaGnhur9tIChJbmZlY3RlZCkgdsOgIGjhu40gY8OzIGto4bqjIG7Eg25nIGzDonkgbmhp4buFbSAoSW5mZWN0aW91cykuIA0KLSBT4buRIG5nxrDhu51pIGjhu5NpIHBo4bulYyAoUmVjb3ZlcmVkKS4gTeG7mXQgc+G7kSB0w6BpIGxp4buHdSB0aMOsIGPDsm4gZ+G7jWkgbMOgIHPhu5EgbmfGsOG7nWkgYuG7iyBn4bqhdCBi4buPIChSZW1vdmVkKSByYSBraOG7j2kgcG9wdWxhdGlvbiBjw7MgdGnhu4FtIG7Eg25nIGfDonkgbmhp4buFbSBi4buHbmggdsOsIHbhuq10IGNo4bunIGLhu4sgY2jhur90IHbDoCBkbyB24bqteSBraMO0bmcgY8OybiBraOG6oyBuxINuZyBsw6J5IGxhbiBi4buHbmguICAgDQoNClbhu4EgY8ahIGLhuqNuIG3DtCBow6xuaCBuw6B5IGPDsyBt4buZdCBnaeG6oyB0aHV54bq/dCAodHJvbmcgc+G7kSBuaGnhu4F1IGdp4bqjIHRodXnhur90KSBy4bqxbmcgdOG7kWMgxJHhu5kgbMOieSBsYW4gY+G7p2EgYuG7h25oIHBo4bulIHRodeG7mWMgdsOgbyBt4buZdCBo4buHIHPhu5EgZ+G7jWkgbMOgIGjhu4cgc+G7kSBsw6J5IG5oaeG7hW0gUm8gKHRyb25nIGtoaSBj4buRIMSR4buLbmggY8OhYyB54bq/dSB04buRIGtow6FjKS4gTuG6v3UgaOG7hyBz4buRIG7DoHkgbcOgIGzhu5tuIHRow6wgc+G7kSBuZ8aw4budaSBi4buLIG5oaeG7hW0gc+G6vSBtYXUgY2jDs25nIMSR4bqhdCBt4buZdCBjw6FpIMSR4buJbmggbsOgbyDEkcOzIHLhu5NpIGdp4bqjbSBuaGFuaCBjaMOzbmcgKHbDrCB24bqtdCBjaOG7pyBi4buLIG5oaeG7hW0gYuG7h25oIMSRw6MgY2jhur90IGPhuqMgbsOqbiB04buRYyDEkeG7mSBsw6J5IGxhbiBz4bq9IGdp4bqjbSkgdsOgIGRvIHbhuq15IGPDoWNoIGvhu4tjaCBi4bqjbiBraMOhYyBuaGF1IGPhu6dhIGThu4tjaCBi4buHbmggdGjDrCBz4bq9IMSRxrDhu6NjIHBow6JuIHTDrWNoIHbDoCDEkcOhbmggZ2nDoSBk4buxYSB2w6BvIGPDoWMga+G7i2NoIGLhuqNuIGtow6FjIG5oYXUgY+G7p2EgUm8uIMSQxrDGoW5nIG5oacOqbiBoaeG7g3UgYmnhur90IHbhu4EgaOG7hyBz4buRIFJvIG7DoHkgbMOgIGzEqW5oIHbhu7FjIGNodXnDqm4gbcO0biBzw6J1IGPhu6dhIG5o4buvbmcgbmfGsOG7nWkgbMOgbSB0cm9uZyBsxKluaCB24buxYyBE4buLY2ggVOG7hSBI4buNYy4gDQoNCiMgU0lSIE1vZGVsaW5nIGluIFINCg0KIEdp4bqjIHPhu60gY2jDum5nIHRhIG114buRbiDEkcOhbmggZ2nDoSBt4bupYyDEkeG7mSBsw6J5IGxhbiBj4bunYSBt4buZdCBsb+G6oWkgYuG7h25oIGThu4tjaCBuw6BvIMSRw7MgYuG6sW5nIG3DtCBow6xuaCBTSVIgdHJvbmcgOTAgbmfDoHkgdOG7m2kgduG7m2kgY8OhYyDEkWnhu4F1IGtp4buHbiBiYW4gxJHhuqd1IChJbml0aWFsIENvbmRpdGlvbnMpIG5oxrAgc2F1OiANCg0KLSBU4bqhaSB0aOG7nWkgxJFp4buDbSBiYW4gxJHhuqd1IHRvIGPDsyAxMCBuZ8aw4budaSBi4buLIG5oaeG7hW0gYuG7h25oIHbDoCBuaOG7r25nIG5nxrDhu51pIG7DoHkgY8OzIGto4bqjIG7Eg25nIGzDonkgdHJ1eeG7gW4gYuG7h25oIGNobyBjw6FjIGPDoSB0aOG7gyBraMOhYyAodsOsIGtow7RuZyDEkcaw4bujYyBjw6FjaCBsaSBjaOG6s25nIGjhuqFuKS4gDQotIFThu5VuZyBkw6JuIHPhu5EgdHJvbmcgY+G7mW5nIMSR4buTbmcgbMOgIDEwMCAoY2jDuiDDvSBy4bqxbmcgdOG6oWkgbeG7jWkgdGjhu51pIMSRaeG7g20gdGjDrCBTICsgSSArIFIgPSBUb3RhbCBQb3B1bGF0aW9uID0gMTAwKS4gDQoNClIgY8OzIGtow6Egbmhp4buBdSB0aMawIHZp4buHbiBjw7MgdGjhu4Mgc+G7rSBk4bulbmcgxJHhu4MgdGjhu7FjIGhp4buHbiBTSVIgKHRyb25nIMSRw7MgY8OzIHRoxrAgdmnhu4duIFtFcGlNb2RlbF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNTkzMTc4OS8pKS4gVHV5IG5oacOqbiB0cm9uZyBwb3N0IG7DoHkgY2jDum5nIHRhIHPhur0gdGjhu7FjIGhp4buHbiBTSVIgaMahaSB0YXkgY2jDom4gbeG7mXQgdMOtIMSR4buDIGhp4buDdSB2aeG7h2MgdHJp4buDbiBraGFpIHThu6sgbcO0IGjDrG5oIHRvw6FuIMSR4bq/biBSIGNvZGVzIGNobyBtw7QgaMOsbmggU0lSIGPhu6dhIFtKYW1lcyBIb2xsYW5kIEpvbmVzXShodHRwczovL3dlYi5zdGFuZm9yZC5lZHUvfmpoajEvdGVhY2hpbmdkb2NzL0pvbmVzLUVwaWRlbWljczA1MDMwOC5wZGYpIHbhu5tpIG3hu5l0IHPhu5EgaGnhu4d1IGNo4buJbmg6IA0KDQoNCg0KYGBge3J9DQojIExvYWQgc29tZSBwYWNrYWdlczogDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShkZVNvbHZlKQ0KDQojIENsZWFyIHdvcmtzcGFjZTogDQpybShsaXN0ID0gbHMoKSkNCg0KIyBTZXQgc29tZSBmaXhlZCBwYXJhbXRlcnMgZm9yIFNJUiBtb2RlbGluZzogDQp0aW1lcyA8LSBzZXEoMCwgOTAsIDEpDQp5MCA8LSBjKDkwLCAxMCwgMCkNCg0KIyBGdW5jdGlvbiBjYWxjdWxhdGVzIFMsIEkgYW5kIFI6IA0KDQpzaXIgPC0gZnVuY3Rpb24odCwgeSwgcCkgew0KICB5ZDEgPC0gLXBbImhvIl0qeVsxXSp5WzJdDQogIHlkMiA8LSBwWyJobyJdKnlbMV0qeVsyXSAtIHBbIm51Il0qeVsyXQ0KICB5ZDMgPC0gcFsibnUiXSp5WzJdDQogIGxpc3QoYyh5ZDEsIHlkMiwgeWQzKSwgYyhOID0gc3VtKHkpKSkNCn0NCg0KIyBXaGVuIGhvID0gMC4wMDEgKHNjZW5hcmlvIDEpOiAgDQoNCnBhcnMxIDwtIGMoImhvIiA9IDAuMDAxLCAibnUiID0gMC4wNSkNCg0Kc2lyLm91dDEgPC0gbHNvZGEoeTAsIHRpbWVzLCBzaXIsIHBhcnMxKQ0KZGF0YS5mcmFtZShzaXIub3V0MSkgLT4gc2lyLm91dF9kZjENCm5hbWVzKHNpci5vdXRfZGYxKSA8LSBjKCJUaW1lIiwgIlN1c2NlcHRpYmxlIiwgIkluZmVjdGVkIiwgIlJlY292ZXJlZCIsICJOIikNCg0Kc2lyLm91dF9kZjEgJT4lIA0KICBtdXRhdGUoVGltZSA9IFRpbWUgKyBkYXRlKG5vdygpKSkgLT4gc2lyLm91dF9kZjENCg0KIyBXaGVuIGhvID0gMC4wMDUgKHNjZW5hcmlvIDIpOiAgDQoNCnBhcnMyIDwtIGMoImhvIiA9IDAuMDA1LCAibnUiID0gMC4wNSkNCg0Kc2lyLm91dDIgPC0gbHNvZGEoeTAsIHRpbWVzLCBzaXIsIHBhcnMyKQ0KZGF0YS5mcmFtZShzaXIub3V0MikgLT4gc2lyLm91dF9kZjINCm5hbWVzKHNpci5vdXRfZGYyKSA8LSBjKCJUaW1lIiwgIlN1c2NlcHRpYmxlIiwgIkluZmVjdGVkIiwgIlJlY292ZXJlZCIsICJOIikNCg0Kc2lyLm91dF9kZjIgJT4lIA0KICBtdXRhdGUoVGltZSA9IFRpbWUgKyBkYXRlKG5vdygpKSkgLT4gc2lyLm91dF9kZjINCg0KIyBQbG90OiANCmxpYnJhcnkoaHJicnRoZW1lcykNCg0KcG9pbnQxIDwtIHNpci5vdXRfZGYxICU+JSBzbGljZSh3aGljaC5tYXgoSW5mZWN0ZWQpKQ0KcG9pbnQyIDwtIHNpci5vdXRfZGYyICU+JSBzbGljZSh3aGljaC5tYXgoSW5mZWN0ZWQpKQ0KDQpzaXIub3V0X2RmMiAlPiUgDQogIHNlbGVjdCgtTikgJT4lIA0KICBnYXRoZXIoVHlwZSwgVmFsdWUsIC1UaW1lKSAlPiUgDQogIGdncGxvdCgoYWVzKFRpbWUsIFZhbHVlLCBjb2xvciA9IFR5cGUpKSkgKyANCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArIA0KICB0aGVtZV9tb2Rlcm5fcmMoKSArIA0KICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxOiBJbmZlY3RlZCBDYXNlcyBwcmVkaWN0ZWQsIFNJUiBBcHByb2FjaCIsIHggPSBOVUxMLCB5ID0gIk51bWJlciBvZiBDYXNlcyIpICsgDQogIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxMikpICsgDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJjeWFuIiwgIm9yYW5nZSIsICJwdXJwbGUiKSwgbmFtZSA9ICIiKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNywgMC41KSkNCmBgYA0KDQoNClNvIHPDoW5oLCB2w60gZOG7pSwgbeG7qWMgxJHhu5kgbMOieSBsYW4gY+G7p2EgYuG7h25oIGThu4tjaCBjxINuIGPhu6kgdGhlbyB0aMaw4bubYyDEkW8gc+G7kSBuZ8aw4budaSBi4buLIG5oaeG6v20gdMawxqFuZyDhu6luZyB24bubaSBoYWkga+G7i2NoIGLhuqNuIGtow6FjIG5oYXUgY+G7p2EgbeG7qWMgxJHhu5kgbMOieSBuaGnhu4VtIHRyb25nIGtoaSBj4buRIMSR4buLbmggY8OhYyB0aGFtIHPhu5Ega2jDoWM6IA0KDQpgYGB7cn0NCmdncGxvdCgpICsgDQogIGdlb21fbGluZShkYXRhID0gc2lyLm91dF9kZjEsIGFlcyhUaW1lLCBJbmZlY3RlZCwgY29sb3IgPSAiU2NlbmFyaW8gMSIpLCBzaXplID0gMSkgKyANCiAgZ2VvbV9wb2ludChkYXRhID0gcG9pbnQxLCBhZXMoVGltZSwgSW5mZWN0ZWQsIGNvbG9yID0gIlNjZW5hcmlvIDEiKSwgc2l6ZSA9IDMpICsgDQogIGdlb21fbGluZShkYXRhID0gc2lyLm91dF9kZjIsIGFlcyhUaW1lLCBJbmZlY3RlZCwgY29sb3IgPSAiU2NlbmFyaW8gMiIpLCBzaXplID0gMSkgKyANCiAgZ2VvbV9wb2ludChkYXRhID0gcG9pbnQyLCBhZXMoVGltZSwgSW5mZWN0ZWQsIGNvbG9yID0gIlNjZW5hcmlvIDIiKSwgc2l6ZSA9IDMpICsgDQogIHRoZW1lX21vZGVybl9yYygpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDcwKSwgYnJlYWtzID0gc2VxKDAsIDcwLCAxMCkpICsgDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJjeWFuIiwgIm9yYW5nZSIpLCBuYW1lID0gIiIpICsgDQogIGxhYnModGl0bGUgPSAiRmlndXJlIDI6IEluZmVjdGVkIENhc2VzIGJ5IFNjZW5hcmlvLCBTSVIgQXBwcm9hY2giLCB4ID0gTlVMTCwgeSA9ICJJbmZlY3RlZCBDYXNlcyIpICsgDQogIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxMikpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC43LCAwLjUpKQ0KDQpgYGANCg0KRmlndXJlIDIgY2jhu4kgcmEgcuG6sW5nIHbhu5tpIGvhu4tjaCBi4bqjbiAyIChjw7MgaOG7hyBz4buRIGzDonkgbmhp4buFbSAwLjAwNSkgdGjDrCBz4bq9IG5oYW5oIGNow7NuZyDEkeG6oXQgxJHhur9uIHPhu5EgbmfGsOG7nWkgYuG7iyBuaGnhu4VtIGLhu4duaCBj4buxYyDEkeG6oWkgKMSRaeG7g20gbcOgdSB2w6BuZykgc2F1IMSRw7MgZ2nhuqNtIG5oYW5oIGNow7NuZy4gTuG6v3UgaOG7hyBz4buRIGzDonkgbmhp4buFbSBnaeG6o20gxJFpIDUgbOG6p24gdGjDrCBz4buRIG5nxrDhu51pIG5oaeG7hW0gxJHhuqF0IGPhu7FjIMSR4bqhaSB0aOG6pXAgaMahbiBjaOG7q25nIDMuNCBs4bqnbiAoxJFp4buDbSBtw6B1IHhhbmgpIG5oxrBuZyBzYXUgxJHDsyB0aMOsIHPhu5EgbmfGsOG7nWkgbmhp4buFbSBz4bq9IGdp4bqjbSBjaOG6rW0gaMahbiBzbyB24bubaSBr4buLY2ggYuG6o24gMSAoY8SDbiBj4bupIHbDoG8gxJHhu5kgZOG7kWMpLiBDw6FpIG7DoHkgY8WpbmcgZOG7hSBoaeG7g3UgdsOsIG7hur91IG3hu5l0IGThu4tjaCBi4buHbmggbcOgIGzDonkgbGFuIG5oYW5oIHRow6wgbmdheSBzYXUga2hpIMSR4bqhdCDEkeG7iW5oLCBz4buRIG5nxrDhu51pIG5oaeG7hW0gc+G6vSBnaeG6o20ga2jDtG5nIHBoYW5oLCB0aOG6rW0gY2jDrSBjw7MgdGjhu4MgdOG7pXQgbmdheSB24buBIHplcm8uIFbDrCB24bqtdCBjaOG7pyBuaGnhu4VtIGLhu4duaCDEkcOjIGNo4bq/dCBo4bq/dCBj4bqjIChSZW1vdmVkKSBob+G6t2MgxJHhuqF0IHRy4bqhbmcgdGjDoWkgxJHGsOG7o2MgbWnhu4VuIGThu4tjaCAoSW1tdW5pdHkpOiBt4buZdCBi4buHbmggZOG7i2NoIGPhu6UgdGjhu4MgdGjDrCBu4bq/dSBt4buZdCBuZ8aw4budaSBi4buLIG5oaeG7hW0gbmjGsG5nIHPhu5FuZyBzw7N0IHRow6wgc+G6vSBraMO0bmcgYmFvIGdp4budIG3huq9jIGzhuqFpIGLhu4duaCDEkcOzIG7hu69hLiANCg0KIyBSZWZlcmVuY2UNCg0KMS4gaHR0cHM6Ly93d3cud2hvLmludC9idWxsZXRpbi9vbmxpbmVfZmlyc3QvMjAtMjU1MTU4LnBkZg0KMi4gaHR0cDovL3NoZXJyeXRvd2Vycy5jb20vMjAxMi8xMi8xMS9zaW1wbGUtZXBpZGVtaWMtbW9kZWxsaW5nLXdpdGgtYW4tc2lyLW1vZGVsLyNlcW4NCg0KDQo=