背景
PS5發售了!但是因為COVID-19的影響所以供貨嚴重不足,許多地方一機難求。就這麼一個周末,閒來沒事,看到有在台灣的玩家討論了巴哈姆特線上商城的PS5主機抽選機制的機率問題,想說好久沒寫R了,就來玩一個玩殺殺時間吧。
抽選池模擬
先從官方的角度出發,寫一支可以模擬抽選結果的函式,使用以下參數:
N
: 玩家數量
X
: 主機數量
R
: 模擬的抽選次數
幾個簡單的假設:
- 一個玩家可以有超過一張抽獎券
- 主機數量遠小於玩家數量
N >> X
(不然抽屁)
- 共抽
X
次,抽獎券抽後不放回,但中獎者其殘餘池裡的抽獎券亦不取出(換言之,一個擁有複數抽獎券的玩家理論上可以抽中超過一台主機,我們後面再來討論這件事情)
library(Matrix)
library(data.table)
#' Run lucky draw simulation
#'
#' @param N Number of players
#' @param n Distribution of draws
#' @param X Number of PS5
#' @param R Number of simulation repetition
#' @return A named list of simulation results and expected outcome for each player
run <- function(N, n, X, R=1e4, seed=666) {
set.seed(seed)
stopifnot(length(n) == N)
draws <- factor(rep(1:N, n)) # the pool: all draws for all players
results <- list()
for ( r in 1:R ) {
results[[r]] <- sample(draws, X, replace=FALSE)
}
# who wins a PS5 for each draw (from 1 to X) at each repetition?
who_wins <- data.table(do.call(rbind, results))
# number of PS5 obtained for each player in a sparse matrix
how_many <- t(Reduce(`+`, lapply(who_wins, function(x) {
x <- factor(x, levels=1:N)
fac2sparse(x, drop.unused.levels=FALSE)
})))
colnames(how_many) <- paste0("player-", colnames(how_many))
list(
expected=colSums(how_many) / R,
who_wins=who_wins,
how_many=how_many,
params=as.list(match.call()) # only works when params are passed explicitly
)
}
為了方便討論所以回傳了:
- 每次模擬(總共
R
次)的每輪中獎者(總共X
輪)
- 每次模擬(總共
R
次)的每個中獎者的取得主機台數
- 模擬結果的每個玩家期望得獎主機台數
小小驗證
假設只有三個玩家爭奪兩台主機,一號跟二號玩家各有兩張抽獎券,可憐的三號玩家則只有一張。
player-1 player-2 player-3
0.7981 0.7943 0.4076
結果顯示三號玩家的中獎期望台數約是0.4。
在這個簡單的環境下,我們可以直接計算理論得獎率來檢查程式的模擬結果是否與理論一致。拿三號玩家來說,因為只有一張抽獎券(總共五張),其得獎機率就是
\[
\underbrace{\frac{1}{5}}_\text{第一抽就中獎} +
\underbrace{\frac{4}{5} \times \frac{1}{4}}_\text{第二抽才中獎} = \frac{2}{5}.
\] 與模擬結果吻合。我們當然可以透過提高模擬次數R
來讓模擬結果無限逼近理論值,比方說從預設的一萬次變成一百萬次:
player-1 player-2 player-3
0.799715 0.800220 0.400065
為了節省時間所以之後都只跑一萬次的結果。
這邊由於三號玩家只有一張抽獎券,所以其中獎率與期望得獎台數會是同一個數字。為了凸顯這件事情,也來算算一號玩家的得獎率吧!這次我們試著反過來算,直接取兩次都沒中的機率
\[
1 - \frac{3}{5} \times \frac{2}{4} = \frac{7}{10}.
\]
得到的結果是70%。我們可以從模擬結果中也計算出對應這個數值的機率(而非期望值):
player-1 player-2 player-3
0.6992 0.6949 0.4076
關於抽獎券的數量,重點是相對而非絕對,所以比方說我們把所有人的抽獎券數量都放大一百倍,結果也不會有任何改變(數字的差異來自抽樣的隨機性):
player-1 player-2 player-3
0.7938 0.8075 0.3987
重複得獎
在我們上面這個小小練習中,玩家一號跟二號因為都投入了複數的抽獎券,所以(根據我們前面做出的簡化假設)他們理論上都有機會抽到超過一台的主機。我們可以把這個機率也算出來:
\[
\underbrace{\frac{2}{5}}_\text{第一台是我的} \times
\underbrace{\frac{1}{4}}_\text{第二台還是我的} = \frac{1}{10}.
\] 或者直接從模擬結果中找到近似值:
player-1 player-2 player-3
0.0989 0.0994 0.0000
這邊玩家三號獲得兩台主機的機率為0,不管模擬幾次都不會改變,因為其只有一張抽獎券。
有趣的事情來了,現實中官方不會真的對同一玩家送出兩台以上的主機,所以勢必會進行重抽。我們現在知道了,就以上這個三人五券情境來講,重抽事件發生的機率正是20%,也就是前兩位玩家獨得主機的機率之和。我們也可以從模擬結果中算出其近似值:
[1] 0.1983
這其實代表,我們前面算出來的三號玩家的得獎機率被低估了,這是因為我們簡化抽獎流程,允許同一名玩家獲得超過一台主機。一個玩家獲得超過一台主機的機率,會隨著兩件事情而增加:
- 該玩家相對於整個抽獎池中所擁有的抽獎券數量
- 總共參與抽獎的PS5主機台數
所以實際上這個被我們忽略的數值其大小,端看現實情況而定。但我們可以拿上面的假想情境來計算看看。對於三號玩家來說,真正的中獎機率應該是沒有重抽且中獎的機率,加上有重抽且中獎的機率,從反面來算的話就是
\[
\underbrace{\frac{2}{5} \times \frac{2}{4}}_\text{第一玩家先中、第二玩家後中} +
\underbrace{\frac{2}{5} \times \frac{2}{4}}_\text{第二玩家先中、第一玩家後中} +
\underbrace{\frac{2}{5} \times \frac{1}{4} \times \frac{2}{3}}_\text{第一玩家全中、重抽後第二玩家中} +
\underbrace{\frac{2}{5} \times \frac{1}{4} \times \frac{2}{3}}_\text{第二玩家全中、重抽後第一玩家中} =
\frac{7}{15} = 0.467.
\] 這和我們原本的模擬結果已經不同,因為我們打破了(因便宜行事而簡化的)玩家可以獲得超過一台主機的假設。要修正這個問題並不困難,我們只要把重抽事件納入考慮,就可以算出玩家的誤差修正機率值。以上面的例子來說,原本玩家三號的簡化得獎率為40%,修正差額就是
\[
\underbrace{20\%}_\text{重抽機率} \times \underbrace{\frac{1}{3}}_\text{重抽時得獎率} = \frac{1}{15} = 0.67.
\]
這邊算式相對簡單是因為其餘兩位玩家有著相同數目的抽獎券。
最後,要注意的是,在上面這個例子中我們不只有低估三號玩家的得獎機率而已。我們低估了所有玩家的得獎機率,因為只要有任何一個玩家有超過一張抽獎券,就會有重抽的可能性,也就等於增加所有其他人的得獎機會。
一人一台啦幹
為了讓這個練習變得更有挑戰性一點,讓我們來把模擬程式納入真實情境考量,限制一名玩家只能獲得一台主機吧!我們的策略是不斷重抽直到沒有任何玩家贏得超過一台的主機。
run2 <- function(N, n, X, R=1e4, seed=666) {
set.seed(seed)
# get simplified results first
results <- do.call(run, as.list(match.call()[-1]))
how_many <- results$how_many
# re=create pool
draws <- factor(rep(1:N, n)) # the pool: all draws for all players
# now consider redraw
calc_n_ps5_for_redraw <- function(how_many) {
redraws <- which(how_many > 1, arr.ind=TRUE)
redraw_ref <- data.table(redraws)
setnames(redraw_ref, c("repetition", "player"))
redraw_ref[, cnt:=how_many[redraws]]
n_release <- redraw_ref[, .(n_release=sum(cnt - 1)), by=.(repetition)]
setkey(n_release, repetition)
}
apply_redraw <- function(n_release) {
repetitions_to_redraw <- n_release$repetition
winners <- data.table(which(how_many > 0, arr.ind=TRUE))
winners <- winners[row %in% repetitions_to_redraw]
winners <- split(winners, by="row", keep.by=FALSE)
new_draws <- lapply(winners, function(x) {
out <- droplevels(draws, x$col)
out[!is.na(out)]
})
new_winners <- mapply(sample, x=new_draws, size=n_release$n_release,
MoreArgs=list(replace=FALSE), SIMPLIFY=FALSE)
# create coordinate ref for sparse matrix update
i <- rep(as.integer(names(new_winners)), sapply(new_winners, length))
j <- as.integer(as.character(unlist(new_winners, use.names=FALSE)))
ij <- data.table(i=i, j=j, v=1)
ij <- ij[, .(cnt=sum(v)), by=list(i, j)] # there could still be duplicated winnings
how_many[as.matrix(ij[, 1:2])] <<- ij$cnt
}
n_release <- calc_n_ps5_for_redraw(how_many)
print(sprintf("Number of repetitions required redraw: %s", nrow(n_release)))
while ( nrow(n_release) ) {
how_many[how_many > 0] <- 1 # reset winning counts
apply_redraw(n_release)
n_release <- calc_n_ps5_for_redraw(how_many)
}
colnames(how_many) <- paste0("player-", colnames(how_many))
list(
expected=colSums(how_many) / R,
how_many=how_many
)
}
我們現在可以用模擬的數值來驗證上面計算的理論機率了。可以注意到一號和二號玩家的得獎機率也獲得向上修正。
[1] "Number of repetitions required redraw: 1983"
player-player-1 player-player-2 player-player-3
0.7642 0.7622 0.4736
現在假設玩家一號不只有兩張抽獎券,而是有十張!在不修正重抽的情況下,三名玩家的贏得主機數量期望值會有很大的差距:
player-1 player-2 player-3
1.5401 0.3013 0.1586
再看看修正重抽後的得獎機率(此時我們不再用期望值來詮釋):
[1] "Number of repetitions required redraw: 5911"
player-player-1 player-player-2 player-player-3
0.9706 0.6714 0.3580
保險起見,我們可以再來驗證一次。對於玩家三號來說,考慮重抽的最終得獎機率應該是
[1] 0.3473193
覺得看起來好像不夠接近模擬結果嗎?我們可以透過放大R
來確保我們的模擬結果會逼近這個數字,差距純粹來自抽樣偏誤。我就把這個差事留給好奇的讀者了。(當然,我私底下已經驗證過了……)
雖然我們設計了嚴謹的重抽模擬,但實際上只要主機數量遠低於玩家數量,兩者的差距就會很小,所以最一開始的簡化假設仍然不失為一個好的近似估計。
僧多粥少的現實
我們試著加大模擬的規模來玩玩,並且設定抽獎券數量跟巴哈姆特第三波活動設計的一樣。假設有一百個人搶三台主機,每個人持有的抽獎券是隨機從設定的七種數量中決定,我們把模擬的得獎結果跟持有抽獎券數量視覺化。
possible_draws <- c(1, 11, 20, 40, 90, 160, 360)
N <- 100
X <- 3
n <- sample(possible_draws, size=N, replace=TRUE)
r2 <- run2(N, n, X)
[1] "Number of repetitions required redraw: 758"
各位可以發現,在一萬次的模擬中只有七百多次出現玩家重複獲獎的情況。我們不需要把玩家數量跟主機數量設定得特別大,因為真正影響結果的是兩這之間的相對差距。把數值無謂地設訂得很大,看似貼近真實,卻只是浪費時間在模擬運算而已。
我們把隨機設定的玩家抽獎券數量分配畫出來如下圖。
這個分配很可能不貼近現實,我們會預期擁有360張的玩家是相對少數,但我懶得調整所以就先這樣吧。
最重要的中獎率與彩券數量關係如下圖。
基本上持有相同張數其理論得獎率是一樣的,所以圖中的誤差來自模擬的隨機性。
我只在乎我自己
上面的練習,我們試圖把所有玩家的得獎機率都追蹤計算,但如果我們只關心一位玩家,那麼其實可以把問題簡化成兩個玩家的問題:我,與不是我的玩家。
假設我是上述情境中只有一張抽獎券的玩家,我可以直接這樣估計:
player-1 player-2
0.0003 2.9997
當然,這只適用於簡化的模擬函式。但是如果我們計算上面模擬結果,所有只有一張抽獎券的玩家的平均得獎率,就會發現兩者是非常近似的:
[1] 0.0003826087
這基本上也展示了為什麼會有簡化假設的理由。
同場加映
上面我們自幹了一個重抽的實作方法,其實是繞了些遠路。像R這種專精於統計問題的程式語言,我們可以很輕鬆地用一行就實現「抽後不放回」與「多重抽獎券」的問題,我們只需要把後者視為加權即可。也就是說,與其手動產生抽獎池,我們可以用sample
函數直接完成任務:
run3 <- function(N, n, X, R=1e4, seed=666) {
set.seed(seed)
stopifnot(length(n) == N)
stopifnot(N >= X)
results <- list()
for ( r in 1:R ) {
results[[r]] <- sample(N, X, replace=FALSE, prob=n)
}
who_wins <- data.table(do.call(rbind, results))
how_many <- t(Reduce(`+`, lapply(who_wins, function(x) {
x <- factor(x, levels=1:N)
fac2sparse(x, drop.unused.levels=FALSE)
})))
colnames(how_many) <- paste0("player-", colnames(how_many))
colSums(how_many) / R
}
檢查結果:
player-1 player-2 player-3
0.7630 0.7601 0.4769
player-1 player-2 player-3
0.9728 0.6734 0.3538
這方法本身效能也會更好,比方說我們重複一百萬次:
player-1 player-2 player-3
0.973089 0.679254 0.347657
等等,那你一開始就這麼寫不就好了?呃,對啊。但這樣文章就太短了。更積極來說,我們想要討論如果多重中獎是可能的,那會如何影響結果,如此一來我們前面自幹的抽獎演算法就能發揮功用了!
好了,遊戲就先到此為止吧。
LS0tCnRpdGxlOiAiQSBTaW11bGF0aW9uIEV4ZXJjaXNlIGZvciBZb3VyIFBTNSBMb3R0ZXJ5IERyYXdzIgpzdWJ0aXRsZTogIuW3tOWTiOWnhueJuVBTNeaKveeNjuaxoOeahOe1seioiOaooeaTrCIKYXV0aG9yOgotIG5hbWU6IEt5bGUgQ2h1bmcKICBhZmZpbGlhdGlvbjoKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJWIgJVknKWAgTGFzdCBVcGRhdGVkICgwNSBEZWMgMjAyMCBGaXJzdCBVcGxvYWRlZCkiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBwYXBlcgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGluY2x1ZGVzOgogICAgICBpbl9oZWFkZXI6IC90bXAvbWV0YV9oZWFkZXIuaHRtbAogIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBtZXRhLCBpbmNsdWRlPUZBTFNFfQptZXRhX2hlYWRlcl9maWxlIDwtIGZpbGUoIi90bXAvbWV0YV9oZWFkZXIuaHRtbCIpCm1ldGEgPC0gYygKICAnPG1ldGEgbmFtZT0iYXV0aG9yIiBjb250ZW50PSJLeWxlIENodW5nIj4nLAogICc8bWV0YSBwcm9wZXJ0eT0ib2c6dGl0bGUiIGNvbnRlbnQ9IuW3tOWTiOWnhueJuVBTNeaKveeNjuaxoOeahOe1seioiOaooeaTrCI+JywKICAnPG1ldGEgcHJvcGVydHk9Im9nOnR5cGUiIGNvbnRlbnQ9ImFydGljbGUiPicsCiAgJzxtZXRhIHByb3BlcnR5PSJvZzp1cmwiIGNvbnRlbnQ9Imh0dHBzOi8vZXZlcmRhcmsuZ2l0aHViLmlvL2s5L3Byb2plY3RzL3BzNS9wczUubmIuaHRtbCI+JywKICAnPG1ldGEgcHJvcGVydHk9Im9nOmRlc2NyaXB0aW9uIiBjb250ZW50PSJBIGRhdGEgc2NpZW5jZSBub3RlYm9vayBhYm91dCBsb3R0ZXJ5IGRyYXcgc2ltdWxhdGlvbi4iPicKKQpjb250ZW50cyA8LSBtZXRhCgojIEFkZCBHaXRodWIgY29ybmVyLgpnaXRodWJfY29ybmVyX3N2ZyA8LSAiLi4vLi4vYXNzZXRzL2dpdGh1Yl9jb3JuZXIuaHRtbCIKZ2l0aHViX2Nvcm5lcl9jb25mIDwtIGxpc3QoZ2l0aHViX2xpbms9Imh0dHBzOi8vZ2l0aHViLmNvbS9ldmVyZGFyay9rOS90cmVlL21hc3Rlci9wcm9qZWN0cy9wczUiKQpjb250ZW50cyA8LSBjKGNvbnRlbnRzLCBzdHJpbmdyOjpzdHJfaW50ZXJwKHJlYWRMaW5lcyhnaXRodWJfY29ybmVyX3N2ZyksIGdpdGh1Yl9jb3JuZXJfY29uZikpCndyaXRlTGluZXMoY29udGVudHMsIG1ldGFfaGVhZGVyX2ZpbGUpCgpjbG9zZShtZXRhX2hlYWRlcl9maWxlKQpgYGAKCiMg6IOM5pmvCgpQUzXnmbzllK7kuobvvIHkvYbmmK/lm6DngrpDT1ZJRC0xOeeahOW9semfv+aJgOS7peS+m+iyqOWatOmHjeS4jei2s++8jOioseWkmuWcsOaWueS4gOapn+mbo+axguOAguWwsemAmem6vOS4gOWAi+WRqOacq++8jOmWkuS+huaykuS6i++8jOeci+WIsOacieWcqOWPsOeBo+eahOeOqeWutuiojuirluS6huW3tOWTiOWnhueJuee3muS4iuWVhuWfjueahFBTNeS4u+apn+aKvemBuOapn+WItueahOapn+eOh+WVj+mhjO+8jOaDs+iqquWlveS5heaykuWvq1LkuobvvIzlsLHkvobnjqnkuIDlgIvnjqnmrrrmrrrmmYLplpPlkKfjgIIKCgojIOaKvemBuOaxoOaooeaTrAoK5YWI5b6e5a6Y5pa555qE6KeS5bqm5Ye655m877yM5a+r5LiA5pSv5Y+v5Lul5qih5pOs5oq96YG457WQ5p6c55qE5Ye95byP77yM5L2/55So5Lul5LiL5Y+D5pW477yaCgorIGBOYDog546p5a625pW46YePCisgYFhgOiDkuLvmqZ/mlbjph48KKyBgUmA6IOaooeaTrOeahOaKvemBuOasoeaVuAoK5bm+5YCL57Ch5Zau55qE5YGH6Kit77yaCgorIOS4gOWAi+eOqeWutuWPr+S7peaciei2hemBjuS4gOW8teaKveeNjuWIuAorIOS4u+apn+aVuOmHj+mBoOWwj+aWvOeOqeWutuaVuOmHjyBgTiA+PiBYYO+8iOS4jeeEtuaKveWxge+8iQorIOWFseaKvWBYYOasoe+8jOaKveeNjuWIuOaKveW+jOS4jeaUvuWbnu+8jOS9huS4reeNjuiAheWFtuaumOmkmOaxoOijoeeahOaKveeNjuWIuOS6puS4jeWPluWHuu+8iOaPm+iogOS5i++8jOS4gOWAi+aTgeacieikh+aVuOaKveeNjuWIuOeahOeOqeWutueQhuirluS4iuWPr+S7peaKveS4rei2hemBjuS4gOWPsOS4u+apn++8jOaIkeWAkeW+jOmdouWGjeS+huiojuirlumAmeS7tuS6i+aDhe+8iQoKCmBgYHtyLCByZXN1bHRzPSdoaWRlJ30KbGlicmFyeShNYXRyaXgpCmxpYnJhcnkoZGF0YS50YWJsZSkKCgojJyBSdW4gbHVja3kgZHJhdyBzaW11bGF0aW9uCiMnCiMnIEBwYXJhbSBOIE51bWJlciBvZiBwbGF5ZXJzCiMnIEBwYXJhbSBuIERpc3RyaWJ1dGlvbiBvZiBkcmF3cwojJyBAcGFyYW0gWCBOdW1iZXIgb2YgUFM1CiMnIEBwYXJhbSBSIE51bWJlciBvZiBzaW11bGF0aW9uIHJlcGV0aXRpb24KIycgQHJldHVybiBBIG5hbWVkIGxpc3Qgb2Ygc2ltdWxhdGlvbiByZXN1bHRzIGFuZCBleHBlY3RlZCBvdXRjb21lIGZvciBlYWNoIHBsYXllcgpydW4gPC0gZnVuY3Rpb24oTiwgbiwgWCwgUj0xZTQsIHNlZWQ9NjY2KSB7CgogIHNldC5zZWVkKHNlZWQpCgogIHN0b3BpZm5vdChsZW5ndGgobikgPT0gTikKICBkcmF3cyA8LSBmYWN0b3IocmVwKDE6TiwgbikpICAjIHRoZSBwb29sOiBhbGwgZHJhd3MgZm9yIGFsbCBwbGF5ZXJzCgogIHJlc3VsdHMgPC0gbGlzdCgpCiAgZm9yICggciBpbiAxOlIgKSB7CiAgICByZXN1bHRzW1tyXV0gPC0gc2FtcGxlKGRyYXdzLCBYLCByZXBsYWNlPUZBTFNFKQogIH0KCiAgIyB3aG8gd2lucyBhIFBTNSBmb3IgZWFjaCBkcmF3IChmcm9tIDEgdG8gWCkgYXQgZWFjaCByZXBldGl0aW9uPwogIHdob193aW5zIDwtIGRhdGEudGFibGUoZG8uY2FsbChyYmluZCwgcmVzdWx0cykpCiAgIyBudW1iZXIgb2YgUFM1IG9idGFpbmVkIGZvciBlYWNoIHBsYXllciBpbiBhIHNwYXJzZSBtYXRyaXgKICBob3dfbWFueSA8LSB0KFJlZHVjZShgK2AsIGxhcHBseSh3aG9fd2lucywgZnVuY3Rpb24oeCkgewogICAgeCA8LSBmYWN0b3IoeCwgbGV2ZWxzPTE6TikKICAgIGZhYzJzcGFyc2UoeCwgZHJvcC51bnVzZWQubGV2ZWxzPUZBTFNFKQogIH0pKSkKCiAgY29sbmFtZXMoaG93X21hbnkpIDwtIHBhc3RlMCgicGxheWVyLSIsIGNvbG5hbWVzKGhvd19tYW55KSkKCiAgbGlzdCgKICAgIGV4cGVjdGVkPWNvbFN1bXMoaG93X21hbnkpIC8gUiwKICAgIHdob193aW5zPXdob193aW5zLAogICAgaG93X21hbnk9aG93X21hbnksCiAgICBwYXJhbXM9YXMubGlzdChtYXRjaC5jYWxsKCkpICAjIG9ubHkgd29ya3Mgd2hlbiBwYXJhbXMgYXJlIHBhc3NlZCBleHBsaWNpdGx5CiAgKQp9CmBgYAoK54K65LqG5pa55L6/6KiO6KuW5omA5Lul5Zue5YKz5LqG77yaCgorIOavj+asoeaooeaTrO+8iOe4veWFsWBSYOasoe+8ieeahOavj+i8quS4reeNjuiAhe+8iOe4veWFsWBYYOi8qu+8iQorIOavj+asoeaooeaTrO+8iOe4veWFsWBSYOasoe+8ieeahOavj+WAi+S4reeNjuiAheeahOWPluW+l+S4u+apn+WPsOaVuAorIOaooeaTrOe1kOaenOeahOavj+WAi+eOqeWutuacn+acm+W+l+eNjuS4u+apn+WPsOaVuAoKCiMg5bCP5bCP6amX6K2JCgrlgYfoqK3lj6rmnInkuInlgIvnjqnlrrbniK3lparlhanlj7DkuLvmqZ/vvIzkuIDomZ/ot5/kuozomZ/njqnlrrblkITmnInlhanlvLXmir3njY7liLjvvIzlj6/mhpDnmoTkuInomZ/njqnlrrbliYflj6rmnInkuIDlvLXjgIIKCgpgYGB7cn0KZXhwMSA8LSBydW4oTj0zLCBuPWMoMiwgMiwgMSksIFg9MikKZXhwMSRleHBlY3RlZApgYGAKCue1kOaenOmhr+ekuuS4ieiZn+eOqeWutueahOS4reeNjuacn+acm+WPsOaVuOe0hOaYrzAuNOOAggoK5Zyo6YCZ5YCL57Ch5Zau55qE55Kw5aKD5LiL77yM5oiR5YCR5Y+v5Lul55u05o6l6KiI566X55CG6KuW5b6X542O546H5L6G5qqi5p+l56iL5byP55qE5qih5pOs57WQ5p6c5piv5ZCm6IiH55CG6KuW5LiA6Ie044CC5ou/5LiJ6Jmf546p5a625L6G6Kqq77yM5Zug54K65Y+q5pyJ5LiA5by15oq9542O5Yi477yI57i95YWx5LqU5by177yJ77yM5YW25b6X542O5qmf546H5bCx5pivCgokJApcdW5kZXJicmFjZXtcZnJhY3sxfXs1fX1fXHRleHR756ys5LiA5oq95bCx5Lit542OfSArClx1bmRlcmJyYWNle1xmcmFjezR9ezV9IFx0aW1lcyBcZnJhY3sxfXs0fX1fXHRleHR756ys5LqM5oq95omN5Lit542OfSA9IFxmcmFjezJ9ezV9LgokJAroiIfmqKHmk6zntZDmnpzlkLvlkIjjgILmiJHlgJHnlbbnhLblj6/ku6XpgI/pgY7mj5Dpq5jmqKHmk6zmrKHmlbhgUmDkvoborpPmqKHmk6zntZDmnpznhKHpmZDpgLzov5HnkIboq5blgLzvvIzmr5Tmlrnoqqrlvp7poJDoqK3nmoTkuIDokKzmrKHorormiJDkuIDnmb7okKzmrKHvvJoKCmBgYHtyfQpydW4oTj0zLCBuPWMoMiwgMiwgMSksIFg9MiwgUj0xZTYpJGV4cGVjdGVkCmBgYAoK54K65LqG56+A55yB5pmC6ZaT5omA5Lul5LmL5b6M6YO95Y+q6LeR5LiA6JCs5qyh55qE57WQ5p6c44CCCgrpgJnpgornlLHmlrzkuInomZ/njqnlrrblj6rmnInkuIDlvLXmir3njY7liLjvvIzmiYDku6XlhbbkuK3njY7njofoiIfmnJ/mnJvlvpfnjY7lj7DmlbjmnIPmmK/lkIzkuIDlgIvmlbjlrZfjgILngrrkuoblh7jpoa/pgJnku7bkuovmg4XvvIzkuZ/kvobnrpfnrpfkuIDomZ/njqnlrrbnmoTlvpfnjY7njoflkKfvvIHpgJnmrKHmiJHlgJHoqabokZflj43pgY7kvobnrpfvvIznm7TmjqXlj5blhanmrKHpg73mspLkuK3nmoTmqZ/njocKCgokJAoxIC0gXGZyYWN7M317NX0gXHRpbWVzIFxmcmFjezJ9ezR9ID0gXGZyYWN7N317MTB9LgokJAoK5b6X5Yiw55qE57WQ5p6c5pivNzAl44CC5oiR5YCR5Y+v5Lul5b6e5qih5pOs57WQ5p6c5Lit5Lmf6KiI566X5Ye65bCN5oeJ6YCZ5YCL5pW45YC855qE5qmf546H77yI6ICM6Z2e5pyf5pyb5YC877yJ77yaCgpgYGB7cn0KY29sU3VtcyhleHAxJGhvd19tYW55ID4gMCkgLyBucm93KGV4cDEkaG93X21hbnkpCmBgYAoK6Zec5pa85oq9542O5Yi455qE5pW46YeP77yM6YeN6bue5piv55u45bCN6ICM6Z2e57WV5bCN77yM5omA5Lul5q+U5pa56Kqq5oiR5YCR5oqK5omA5pyJ5Lq655qE5oq9542O5Yi45pW46YeP6YO95pS+5aSn5LiA55m+5YCN77yM57WQ5p6c5Lmf5LiN5pyD5pyJ5Lu75L2V5pS56K6K77yI5pW45a2X55qE5beu55Ww5L6G6Ieq5oq95qij55qE6Zqo5qmf5oCn77yJ77yaCgpgYGB7cn0KcnVuKE49Mywgbj1jKDIsIDIsIDEpKjEwMCwgWD0yKSRleHBlY3RlZApgYGAKCiMg6YeN6KSH5b6X542OCgrlnKjmiJHlgJHkuIrpnaLpgJnlgIvlsI/lsI/nt7Tnv5LkuK3vvIznjqnlrrbkuIDomZ/ot5/kuozomZ/lm6Dngrrpg73mipXlhaXkuobopIfmlbjnmoTmir3njY7liLjvvIzmiYDku6XvvIjmoLnmk5rmiJHlgJHliY3pnaLlgZrlh7rnmoTnsKHljJblgYfoqK3vvInku5blgJHnkIboq5bkuIrpg73mnInmqZ/mnIPmir3liLDotoXpgY7kuIDlj7DnmoTkuLvmqZ/jgILmiJHlgJHlj6/ku6XmiorpgJnlgIvmqZ/njofkuZ/nrpflh7rkvobvvJoKCiQkClx1bmRlcmJyYWNle1xmcmFjezJ9ezV9fV9cdGV4dHvnrKzkuIDlj7DmmK/miJHnmoR9IFx0aW1lcwpcdW5kZXJicmFjZXtcZnJhY3sxfXs0fX1fXHRleHR756ys5LqM5Y+w6YKE5piv5oiR55qEfSA9IFxmcmFjezF9ezEwfS4KJCQK5oiW6ICF55u05o6l5b6e5qih5pOs57WQ5p6c5Lit5om+5Yiw6L+R5Ly85YC877yaCgpgYGB7cn0KY29sU3VtcyhleHAxJGhvd19tYW55ID4gMSkgLyBucm93KGV4cDEkaG93X21hbnkpCmBgYAoK6YCZ6YKK546p5a625LiJ6Jmf542y5b6X5YWp5Y+w5Li75qmf55qE5qmf546H54K6MO+8jOS4jeeuoeaooeaTrOW5vuasoemDveS4jeacg+aUueiuiu+8jOWboOeCuuWFtuWPquacieS4gOW8teaKveeNjuWIuOOAggoK5pyJ6Laj55qE5LqL5oOF5L6G5LqG77yM54++5a+m5Lit5a6Y5pa55LiN5pyD55yf55qE5bCN5ZCM5LiA546p5a626YCB5Ye65YWp5Y+w5Lul5LiK55qE5Li75qmf77yM5omA5Lul5Yui5b+F5pyD6YCy6KGM6YeN5oq944CC5oiR5YCR54++5Zyo55+l6YGT5LqG77yM5bCx5Lul5LiK6YCZ5YCL5LiJ5Lq65LqU5Yi45oOF5aKD5L6G6Kyb77yM6YeN5oq95LqL5Lu255m855Sf55qE5qmf546H5q2j5pivMjAl77yM5Lmf5bCx5piv5YmN5YWp5L2N546p5a62542o5b6X5Li75qmf55qE5qmf546H5LmL5ZKM44CC5oiR5YCR5Lmf5Y+v5Lul5b6e5qih5pOs57WQ5p6c5Lit566X5Ye65YW26L+R5Ly85YC877yaCgoKYGBge3J9Cm5yb3coZXhwMSR3aG9fd2luc1tWMSA9PSBWMl0pIC8gbnJvdyhleHAxJHdob193aW5zKQpgYGAKCumAmeWFtuWvpuS7o+ihqO+8jOaIkeWAkeWJjemdoueul+WHuuS+hueahOS4ieiZn+eOqeWutueahOW+l+eNjuapn+eOh+iiq+S9juS8sOS6hu+8jOmAmeaYr+WboOeCuuaIkeWAkeewoeWMluaKveeNjua1geeoi++8jOWFgeioseWQjOS4gOWQjeeOqeWutueNsuW+l+i2hemBjuS4gOWPsOS4u+apn+OAguS4gOWAi+eOqeWutueNsuW+l+i2hemBjuS4gOWPsOS4u+apn+eahOapn+eOh++8jOacg+maqOiRl+WFqeS7tuS6i+aDheiAjOWinuWKoO+8mgoKKyDoqbLnjqnlrrbnm7jlsI3mlrzmlbTlgIvmir3njY7msaDkuK3miYDmk4HmnInnmoTmir3njY7liLjmlbjph48KKyDnuL3lhbHlj4PoiIfmir3njY7nmoRQUzXkuLvmqZ/lj7DmlbgKCuaJgOS7peWvpumam+S4iumAmeWAi+iiq+aIkeWAkeW/veeVpeeahOaVuOWAvOWFtuWkp+Wwj++8jOerr+eci+ePvuWvpuaDheazgeiAjOWumuOAguS9huaIkeWAkeWPr+S7peaLv+S4iumdoueahOWBh+aDs+aDheWig+S+huioiOeul+eci+eci+OAguWwjeaWvOS4ieiZn+eOqeWutuS+huiqqu+8jOecn+ato+eahOS4reeNjuapn+eOh+aHieipsuaYr+aykuaciemHjeaKveS4lOS4reeNjueahOapn+eOh++8jOWKoOS4iuaciemHjeaKveS4lOS4reeNjueahOapn+eOh++8jOW+nuWPjemdouS+hueul+eahOipseWwseaYrwoKJCQKXHVuZGVyYnJhY2V7XGZyYWN7Mn17NX0gXHRpbWVzIFxmcmFjezJ9ezR9fV9cdGV4dHvnrKzkuIDnjqnlrrblhYjkuK3jgIHnrKzkuoznjqnlrrblvozkuK19ICsKXHVuZGVyYnJhY2V7XGZyYWN7Mn17NX0gXHRpbWVzIFxmcmFjezJ9ezR9fV9cdGV4dHvnrKzkuoznjqnlrrblhYjkuK3jgIHnrKzkuIDnjqnlrrblvozkuK19ICsKXHVuZGVyYnJhY2V7XGZyYWN7Mn17NX0gXHRpbWVzIFxmcmFjezF9ezR9IFx0aW1lcyBcZnJhY3syfXszfX1fXHRleHR756ys5LiA546p5a625YWo5Lit44CB6YeN5oq95b6M56ys5LqM546p5a625LitfSArClx1bmRlcmJyYWNle1xmcmFjezJ9ezV9IFx0aW1lcyBcZnJhY3sxfXs0fSBcdGltZXMgXGZyYWN7Mn17M319X1x0ZXh0e+esrOS6jOeOqeWutuWFqOS4reOAgemHjeaKveW+jOesrOS4gOeOqeWutuS4rX0gPQpcZnJhY3s3fXsxNX0gPSAwLjQ2Ny4KJCQK6YCZ5ZKM5oiR5YCR5Y6f5pys55qE5qih5pOs57WQ5p6c5bey57aT5LiN5ZCM77yM5Zug54K65oiR5YCR5omT56C05LqG77yI5Zug5L6/5a6c6KGM5LqL6ICM57Ch5YyW55qE77yJ546p5a625Y+v5Lul542y5b6X6LaF6YGO5LiA5Y+w5Li75qmf55qE5YGH6Kit44CC6KaB5L+u5q2j6YCZ5YCL5ZWP6aGM5Lim5LiN5Zuw6Zuj77yM5oiR5YCR5Y+q6KaB5oqK6YeN5oq95LqL5Lu257SN5YWl6ICD5oWu77yM5bCx5Y+v5Lul566X5Ye6546p5a6255qE6Kqk5beu5L+u5q2j5qmf546H5YC844CC5Lul5LiK6Z2i55qE5L6L5a2Q5L6G6Kqq77yM5Y6f5pys546p5a625LiJ6Jmf55qE57Ch5YyW5b6X542O546H54K6NDAl77yM5L+u5q2j5beu6aGN5bCx5pivCgokJApcdW5kZXJicmFjZXsyMFwlfV9cdGV4dHvph43mir3mqZ/njod9IFx0aW1lcyBcdW5kZXJicmFjZXtcZnJhY3sxfXszfX1fXHRleHR76YeN5oq95pmC5b6X542O546HfSA9IFxmcmFjezF9ezE1fSA9IDAuNjcuCiQkCgrpgJnpgornrpflvI/nm7jlsI3nsKHllq7mmK/lm6DngrrlhbbppJjlhankvY3njqnlrrbmnInokZfnm7jlkIzmlbjnm67nmoTmir3njY7liLjjgIIKCuacgOW+jO+8jOimgeazqOaEj+eahOaYr++8jOWcqOS4iumdoumAmeWAi+S+i+WtkOS4reaIkeWAkeS4jeWPquacieS9juS8sOS4ieiZn+eOqeWutueahOW+l+eNjuapn+eOh+iAjOW3suOAguaIkeWAkeS9juS8sOS6huaJgOacieeOqeWutueahOW+l+eNjuapn+eOh++8jOWboOeCuuWPquimgeacieS7u+S9leS4gOWAi+eOqeWutuaciei2hemBjuS4gOW8teaKveeNjuWIuO+8jOWwseacg+aciemHjeaKveeahOWPr+iDveaAp++8jOS5n+WwseetieaWvOWinuWKoOaJgOacieWFtuS7luS6uueahOW+l+eNjuapn+acg+OAggoKCiMg5LiA5Lq65LiA5Y+w5ZWm5bm5CgrngrrkuoborpPpgJnlgIvnt7Tnv5Lororlvpfmm7TmnInmjJHmiLDmgKfkuIDpu57vvIzorpPmiJHlgJHkvobmiormqKHmk6znqIvlvI/ntI3lhaXnnJ/lr6bmg4XlooPogIPph4/vvIzpmZDliLbkuIDlkI3njqnlrrblj6rog73njbLlvpfkuIDlj7DkuLvmqZ/lkKfvvIHmiJHlgJHnmoTnrZbnlaXmmK/kuI3mlrfph43mir3nm7TliLDmspLmnInku7vkvZXnjqnlrrbotI/lvpfotoXpgY7kuIDlj7DnmoTkuLvmqZ/jgIIKCgpgYGB7cn0KcnVuMiA8LSBmdW5jdGlvbihOLCBuLCBYLCBSPTFlNCwgc2VlZD02NjYpIHsKCiAgc2V0LnNlZWQoc2VlZCkKCiAgIyBnZXQgc2ltcGxpZmllZCByZXN1bHRzIGZpcnN0CiAgcmVzdWx0cyA8LSBkby5jYWxsKHJ1biwgYXMubGlzdChtYXRjaC5jYWxsKClbLTFdKSkKICBob3dfbWFueSA8LSByZXN1bHRzJGhvd19tYW55CiAgIyByZT1jcmVhdGUgcG9vbAogIGRyYXdzIDwtIGZhY3RvcihyZXAoMTpOLCBuKSkgICMgdGhlIHBvb2w6IGFsbCBkcmF3cyBmb3IgYWxsIHBsYXllcnMKCiAgIyBub3cgY29uc2lkZXIgcmVkcmF3CiAgY2FsY19uX3BzNV9mb3JfcmVkcmF3IDwtIGZ1bmN0aW9uKGhvd19tYW55KSB7CiAgICByZWRyYXdzIDwtIHdoaWNoKGhvd19tYW55ID4gMSwgYXJyLmluZD1UUlVFKQogICAgcmVkcmF3X3JlZiA8LSBkYXRhLnRhYmxlKHJlZHJhd3MpCiAgICBzZXRuYW1lcyhyZWRyYXdfcmVmLCBjKCJyZXBldGl0aW9uIiwgInBsYXllciIpKQogICAgcmVkcmF3X3JlZlssIGNudDo9aG93X21hbnlbcmVkcmF3c11dCiAgICBuX3JlbGVhc2UgPC0gcmVkcmF3X3JlZlssIC4obl9yZWxlYXNlPXN1bShjbnQgLSAxKSksIGJ5PS4ocmVwZXRpdGlvbildCiAgICBzZXRrZXkobl9yZWxlYXNlLCByZXBldGl0aW9uKQogIH0KCiAgYXBwbHlfcmVkcmF3IDwtIGZ1bmN0aW9uKG5fcmVsZWFzZSkgewogICAgcmVwZXRpdGlvbnNfdG9fcmVkcmF3IDwtIG5fcmVsZWFzZSRyZXBldGl0aW9uCiAgICB3aW5uZXJzIDwtIGRhdGEudGFibGUod2hpY2goaG93X21hbnkgPiAwLCBhcnIuaW5kPVRSVUUpKQogICAgd2lubmVycyA8LSB3aW5uZXJzW3JvdyAlaW4lIHJlcGV0aXRpb25zX3RvX3JlZHJhd10KICAgIHdpbm5lcnMgPC0gc3BsaXQod2lubmVycywgYnk9InJvdyIsIGtlZXAuYnk9RkFMU0UpCiAgICBuZXdfZHJhd3MgPC0gbGFwcGx5KHdpbm5lcnMsIGZ1bmN0aW9uKHgpIHsKICAgICAgb3V0IDwtIGRyb3BsZXZlbHMoZHJhd3MsIHgkY29sKQogICAgICBvdXRbIWlzLm5hKG91dCldCiAgICB9KQogICAgbmV3X3dpbm5lcnMgPC0gbWFwcGx5KHNhbXBsZSwgeD1uZXdfZHJhd3MsIHNpemU9bl9yZWxlYXNlJG5fcmVsZWFzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICBNb3JlQXJncz1saXN0KHJlcGxhY2U9RkFMU0UpLCBTSU1QTElGWT1GQUxTRSkKICAgICMgY3JlYXRlIGNvb3JkaW5hdGUgcmVmIGZvciBzcGFyc2UgbWF0cml4IHVwZGF0ZQogICAgaSA8LSByZXAoYXMuaW50ZWdlcihuYW1lcyhuZXdfd2lubmVycykpLCBzYXBwbHkobmV3X3dpbm5lcnMsIGxlbmd0aCkpCiAgICBqIDwtIGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKHVubGlzdChuZXdfd2lubmVycywgdXNlLm5hbWVzPUZBTFNFKSkpCiAgICBpaiA8LSBkYXRhLnRhYmxlKGk9aSwgaj1qLCB2PTEpCiAgICBpaiA8LSBpalssIC4oY250PXN1bSh2KSksIGJ5PWxpc3QoaSwgaildICAjIHRoZXJlIGNvdWxkIHN0aWxsIGJlIGR1cGxpY2F0ZWQgd2lubmluZ3MKICAgIGhvd19tYW55W2FzLm1hdHJpeChpalssIDE6Ml0pXSA8PC0gaWokY250CiAgfQoKICBuX3JlbGVhc2UgPC0gY2FsY19uX3BzNV9mb3JfcmVkcmF3KGhvd19tYW55KQogIHByaW50KHNwcmludGYoIk51bWJlciBvZiByZXBldGl0aW9ucyByZXF1aXJlZCByZWRyYXc6ICVzIiwgbnJvdyhuX3JlbGVhc2UpKSkKICB3aGlsZSAoIG5yb3cobl9yZWxlYXNlKSApIHsKICAgIGhvd19tYW55W2hvd19tYW55ID4gMF0gPC0gMSAgIyByZXNldCB3aW5uaW5nIGNvdW50cwogICAgYXBwbHlfcmVkcmF3KG5fcmVsZWFzZSkKICAgIG5fcmVsZWFzZSA8LSBjYWxjX25fcHM1X2Zvcl9yZWRyYXcoaG93X21hbnkpCiAgfQoKICBjb2xuYW1lcyhob3dfbWFueSkgPC0gcGFzdGUwKCJwbGF5ZXItIiwgY29sbmFtZXMoaG93X21hbnkpKQoKICBsaXN0KAogICAgZXhwZWN0ZWQ9Y29sU3Vtcyhob3dfbWFueSkgLyBSLAogICAgaG93X21hbnk9aG93X21hbnkKICApCn0KYGBgCgrmiJHlgJHnj77lnKjlj6/ku6XnlKjmqKHmk6znmoTmlbjlgLzkvobpqZforYnkuIrpnaLoqIjnrpfnmoTnkIboq5bmqZ/njofkuobjgILlj6/ku6Xms6jmhI/liLDkuIDomZ/lkozkuozomZ/njqnlrrbnmoTlvpfnjY7mqZ/njofkuZ/njbLlvpflkJHkuIrkv67mraPjgIIKCmBgYHtyfQpleHAxX3JlYWwgPC0gcnVuMihOPTMsIG49YygyLCAyLCAxKSwgWD0yKQpleHAxX3JlYWwkZXhwZWN0ZWQKYGBgCgrnj77lnKjlgYfoqK3njqnlrrbkuIDomZ/kuI3lj6rmnInlhanlvLXmir3njY7liLjvvIzogIzmmK/mnInljYHlvLXvvIHlnKjkuI3kv67mraPph43mir3nmoTmg4Xms4HkuIvvvIzkuInlkI3njqnlrrbnmoTotI/lvpfkuLvmqZ/mlbjph4/mnJ/mnJvlgLzmnIPmnInlvojlpKfnmoTlt67ot53vvJoKCmBgYHtyfQpleHAyIDwtIHJ1bihOPTMsIG49YygxMCwgMiwgMSksIFg9MikKZXhwMiRleHBlY3RlZApgYGAKCuWGjeeci+eci+S/ruato+mHjeaKveW+jOeahOW+l+eNjuapn+eOh++8iOatpOaZguaIkeWAkeS4jeWGjeeUqOacn+acm+WAvOS+huiprumHi++8ie+8mgoKYGBge3J9CmV4cDJfcmVhbCA8LSBydW4yKE49Mywgbj1jKDEwLCAyLCAxKSwgWD0yKQpleHAyX3JlYWwkZXhwZWN0ZWQKYGBgCgrkv53pmqrotbfopovvvIzmiJHlgJHlj6/ku6Xlho3kvobpqZforYnkuIDmrKHjgILlsI3mlrznjqnlrrbkuInomZ/kvoboqqrvvIzogIPmha7ph43mir3nmoTmnIDntYLlvpfnjY7mqZ/njofmh4noqbLmmK8KCmBgYHtyfQoxIC0gKDEwLzEzKjIvMTIgKyAyLzEzKjEwLzEyICsgMTAvMTMqOS8xMioyLzMgKyAyLzEzKjEvMTIqMTAvMTEpCmBgYAoK6Ka65b6X55yL6LW35L6G5aW95YOP5LiN5aSg5o6l6L+R5qih5pOs57WQ5p6c5ZeO77yf5oiR5YCR5Y+v5Lul6YCP6YGO5pS+5aSnYFJg5L6G56K65L+d5oiR5YCR55qE5qih5pOs57WQ5p6c5pyD6YC86L+R6YCZ5YCL5pW45a2X77yM5beu6Led57SU57K55L6G6Ieq5oq95qij5YGP6Kqk44CC5oiR5bCx5oqK6YCZ5YCL5beu5LqL55WZ57Wm5aW95aWH55qE6K6A6ICF5LqG44CC77yI55W254S277yM5oiR56eB5bqV5LiL5bey57aT6amX6K2J6YGO5LqG4oCm4oCm77yJCgrpm5bnhLbmiJHlgJHoqK3oqIjkuoblmrTorLnnmoTph43mir3mqKHmk6zvvIzkvYblr6bpmpvkuIrlj6ropoHkuLvmqZ/mlbjph4/pgaDkvY7mlrznjqnlrrbmlbjph4/vvIzlhanogIXnmoTlt67ot53lsLHmnIPlvojlsI/vvIzmiYDku6XmnIDkuIDplovlp4vnmoTnsKHljJblgYfoqK3ku43nhLbkuI3lpLHngrrkuIDlgIvlpb3nmoTov5HkvLzkvLDoqIjjgIIKCiMg5YOn5aSa57Kl5bCR55qE54++5a+mCgrmiJHlgJHoqabokZfliqDlpKfmqKHmk6znmoTopo/mqKHkvobnjqnnjqnvvIzkuKbkuJToqK3lrprmir3njY7liLjmlbjph4/ot5/lt7Tlk4jlp4bnibnnrKzkuInms6LmtLvli5XoqK3oqIjnmoTkuIDmqKPjgILlgYfoqK3mnInkuIDnmb7lgIvkurrmkLbkuInlj7DkuLvmqZ/vvIzmr4/lgIvkurrmjIHmnInnmoTmir3njY7liLjmmK/pmqjmqZ/lvp7oqK3lrprnmoTkuIPnqK7mlbjph4/kuK3msbrlrprvvIzmiJHlgJHmiormqKHmk6znmoTlvpfnjY7ntZDmnpzot5/mjIHmnInmir3njY7liLjmlbjph4/oppboprrljJbjgIIKCmBgYHtyfQpwb3NzaWJsZV9kcmF3cyA8LSBjKDEsIDExLCAyMCwgNDAsIDkwLCAxNjAsIDM2MCkKTiA8LSAxMDAKWCA8LSAzCm4gPC0gc2FtcGxlKHBvc3NpYmxlX2RyYXdzLCBzaXplPU4sIHJlcGxhY2U9VFJVRSkKCnIyIDwtIHJ1bjIoTiwgbiwgWCkKYGBgCgrlkITkvY3lj6/ku6Xnmbznj77vvIzlnKjkuIDokKzmrKHnmoTmqKHmk6zkuK3lj6rmnInkuIPnmb7lpJrmrKHlh7rnj77njqnlrrbph43opIfnjbLnjY7nmoTmg4Xms4HjgILmiJHlgJHkuI3pnIDopoHmiornjqnlrrbmlbjph4/ot5/kuLvmqZ/mlbjph4/oqK3lrprlvpfnibnliKXlpKfvvIzlm6DngrrnnJ/mraPlvbHpn7/ntZDmnpznmoTmmK/lhanpgJnkuYvplpPnmoTnm7jlsI3lt67ot53jgILmiormlbjlgLznhKHorILlnLDoqK3oqILlvpflvojlpKfvvIznnIvkvLzosrzov5HnnJ/lr6bvvIzljbvlj6rmmK/mtarosrvmmYLplpPlnKjmqKHmk6zpgYvnrpfogIzlt7LjgIIKCuaIkeWAkeaKiumaqOapn+ioreWumueahOeOqeWutuaKveeNjuWIuOaVuOmHj+WIhumFjeeVq+WHuuS+huWmguS4i+WcluOAggoKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CmJhcnBsb3QodGFibGUobiksIG1haW49IueOqeWutuaKveeNjuWIuOaVuOmHj+WIhumFjSIpCmBgYAoK6YCZ5YCL5YiG6YWN5b6I5Y+v6IO95LiN6LK86L+R54++5a+m77yM5oiR5YCR5pyD6aCQ5pyf5pOB5pyJMzYw5by155qE546p5a625piv55u45bCN5bCR5pW477yM5L2G5oiR5oe25b6X6Kq/5pW05omA5Lul5bCx5YWI6YCZ5qij5ZCn44CCCgrmnIDph43opoHnmoTkuK3njY7njofoiIflvanliLjmlbjph4/pl5zkv4LlpoLkuIvlnJbjgIIKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQoKZDIgPC0gZGF0YS50YWJsZShuX2RyYXdzPW4sIGV4cGVjdGVkPXIyJGV4cGVjdGVkKQpmaWcgPC1nZ3Bsb3QoZDIsIGFlcyh4PWZhY3RvcihuX2RyYXdzKSwgeT1leHBlY3RlZCkpICsKICBnZW9tX3BvaW50KCkgKwogIGxhYnMoeD0i5oq9542O5Yi45pW46YePIiwgeT0i5Lit542O546HIikKCmdncGxvdGx5KGZpZykKYGBgCgrln7rmnKzkuIrmjIHmnInnm7jlkIzlvLXmlbjlhbbnkIboq5blvpfnjY7njofmmK/kuIDmqKPnmoTvvIzmiYDku6XlnJbkuK3nmoToqqTlt67kvoboh6rmqKHmk6znmoTpmqjmqZ/mgKfjgIIKCiMg5oiR5Y+q5Zyo5LmO5oiR6Ieq5bexCgrkuIrpnaLnmoTnt7Tnv5LvvIzmiJHlgJHoqablnJbmiormiYDmnInnjqnlrrbnmoTlvpfnjY7mqZ/njofpg73ov73ouaToqIjnrpfvvIzkvYblpoLmnpzmiJHlgJHlj6rpl5zlv4PkuIDkvY3njqnlrrbvvIzpgqPpurzlhbblr6blj6/ku6XmiorllY/poYznsKHljJbmiJDlhanlgIvnjqnlrrbnmoTllY/poYzvvJrmiJHvvIzoiIfkuI3mmK/miJHnmoTnjqnlrrbjgIIKCuWBh+ioreaIkeaYr+S4iui/sOaDheWig+S4reWPquacieS4gOW8teaKveeNjuWIuOeahOeOqeWutu+8jOaIkeWPr+S7peebtOaOpemAmeaoo+S8sOioiO+8mgoKYGBge3J9CnJ1bihOPTIsIG49YygxLCBzdW0obikgLSAxKSwgWD0zKSRleHBlY3RlZApgYGAKCueVtueEtu+8jOmAmeWPqumBqeeUqOaWvOewoeWMlueahOaooeaTrOWHveW8j+OAguS9huaYr+WmguaenOaIkeWAkeioiOeul+S4iumdouaooeaTrOe1kOaenO+8jOaJgOacieWPquacieS4gOW8teaKveeNjuWIuOeahOeOqeWutueahOW5s+Wdh+W+l+eNjueOh++8jOWwseacg+eZvOePvuWFqeiAheaYr+mdnuW4uOi/keS8vOeahO+8mgoKYGBge3J9CmQyW25fZHJhd3MgPT0gMSwgbWVhbihleHBlY3RlZCldCmBgYAoK6YCZ5Z+65pys5LiK5Lmf5bGV56S65LqG54K65LuA6bq85pyD5pyJ57Ch5YyW5YGH6Kit55qE55CG55Sx44CCCgojIOWQjOWgtOWKoOaYoAoK5LiK6Z2i5oiR5YCR6Ieq5bm55LqG5LiA5YCL6YeN5oq955qE5a+m5L2c5pa55rOV77yM5YW25a+m5piv57me5LqG5Lqb6YGg6Lev44CC5YOPUumAmeeoruWwiOeyvuaWvOe1seioiOWVj+mhjOeahOeoi+W8j+iqnuiogO+8jOaIkeWAkeWPr+S7peW+iOi8lemshuWcsOeUqOS4gOihjOWwseWvpuePvuOAjOaKveW+jOS4jeaUvuWbnuOAjeiIh+OAjOWkmumHjeaKveeNjuWIuOOAjeeahOWVj+mhjO+8jOaIkeWAkeWPqumcgOimgeaKiuW+jOiAheimlueCuuWKoOasiuWNs+WPr+OAguS5n+WwseaYr+iqqu+8jOiIh+WFtuaJi+WLleeUoueUn+aKveeNjuaxoO+8jOaIkeWAkeWPr+S7peeUqGBzYW1wbGVg5Ye95pW455u05o6l5a6M5oiQ5Lu75YuZ77yaCgpgYGB7cn0KcnVuMyA8LSBmdW5jdGlvbihOLCBuLCBYLCBSPTFlNCwgc2VlZD02NjYpIHsKCiAgc2V0LnNlZWQoc2VlZCkKCiAgc3RvcGlmbm90KGxlbmd0aChuKSA9PSBOKQogIHN0b3BpZm5vdChOID49IFgpCgogIHJlc3VsdHMgPC0gbGlzdCgpCiAgZm9yICggciBpbiAxOlIgKSB7CiAgICByZXN1bHRzW1tyXV0gPC0gc2FtcGxlKE4sIFgsIHJlcGxhY2U9RkFMU0UsIHByb2I9bikKICB9CgogIHdob193aW5zIDwtIGRhdGEudGFibGUoZG8uY2FsbChyYmluZCwgcmVzdWx0cykpCiAgaG93X21hbnkgPC0gdChSZWR1Y2UoYCtgLCBsYXBwbHkod2hvX3dpbnMsIGZ1bmN0aW9uKHgpIHsKICAgIHggPC0gZmFjdG9yKHgsIGxldmVscz0xOk4pCiAgICBmYWMyc3BhcnNlKHgsIGRyb3AudW51c2VkLmxldmVscz1GQUxTRSkKICB9KSkpCiAgY29sbmFtZXMoaG93X21hbnkpIDwtIHBhc3RlMCgicGxheWVyLSIsIGNvbG5hbWVzKGhvd19tYW55KSkKICBjb2xTdW1zKGhvd19tYW55KSAvIFIKfQpgYGAKCuaqouafpee1kOaenO+8mgoKYGBge3J9CnJ1bjMoTj0zLCBuPWMoMiwgMiwgMSksIFg9MikKYGBgCmBgYHtyfQpydW4zKE49Mywgbj1jKDEwLCAyLCAxKSwgWD0yKQpgYGAKCumAmeaWueazleacrOi6q+aViOiDveS5n+acg+abtOWlve+8jOavlOaWueiqquaIkeWAkemHjeikh+S4gOeZvuiQrOasoe+8mgoKYGBge3J9CnJ1bjMoTj0zLCBuPWMoMTAsIDIsIDEpLCBYPTIsIFI9MWU2KQpgYGAKCuetieetie+8jOmCo+S9oOS4gOmWi+Wni+WwsemAmem6vOWvq+S4jeWwseWlveS6hj/lkYPvvIzlsI3llYrjgILkvYbpgJnmqKPmlofnq6DlsLHlpKrnn63kuobjgILmm7TnqY3mpbXkvoboqqrvvIzmiJHlgJHmg7PopoHoqI7oq5blpoLmnpzlpJrph43kuK3njY7mmK/lj6/og73nmoTvvIzpgqPmnIPlpoLkvZXlvbHpn7/ntZDmnpzvvIzlpoLmraTkuIDkvobmiJHlgJHliY3pnaLoh6rlubnnmoTmir3njY7mvJTnrpfms5XlsLHog73nmbzmj67lip/nlKjkuobvvIEKCgrlpb3kuobvvIzpgYrmiLLlsLHlhYjliLDmraTngrrmraLlkKfjgIIKCiMg57WQ6KqeCgrmiJHmspLmnIlQUzXjgIIK