###############################################################################
# simulacao jogo craps
# pedro carvalho brom
#
# regras:
# 1. obervar a soma dos resultados das faces superiores de 
#    02 dados equilibrados.
# 2. anotar o resultado.
# 3. se resultado == 7 ou 11 entao: T.
#    se resultado == 2, 3 ou 12 entao: F.
#    cc resultado != 2, 3, 7, 11 ou 12 entao:
#       realizar novo lançamento até:
#         sair 7: F.
#         sair o mesmo resultado que em 1: T.
###############################################################################

# marcador de tempo de processamento
t0 <- Sys.time()

suppressMessages({
  suppressWarnings({
    library(dplyr)
    library(ggplot2)
    library(gganimate)
    library(doSNOW)
  })
})
set.seed(123)

# testando o lançamento de dados.
sample(1:6, 1) + sample(1:6, 1)
## [1] 9
# valor observado: soma das faces superiores.
get_dice <- function() sample(1:6, 1) + sample(1:6, 1)
(r1 <- get_dice())
## [1] 5
# simulando uma partida.
r1 <- get_dice()
if(r1 %in% c(7, 11)) {
  fim <- T
  n <- NA
} else if (r1 %in% c(2, 3, 12)) {
  fim <- F
  n <- NA
} else {
  n <- 0
  while(T) {
    r2 <- get_dice()
    if (r2 == 7) {
      fim <- F
      break
    } 
    if (r2 == r1) {
      fim <- T
      n <- n + 1
      break
    }
  }
}
fim; n
## [1] TRUE
## [1] 1
# simulando jogos -------------------------------------------------------------

# funcao de jogo
get_game <- function() {
  r1 <- get_dice()
  if(r1 %in% c(7, 11)) {
    fim <- T
    n <- NA
  } else if (r1 %in% c(2, 3, 12)) {
    fim <- F
    n <- NA
  } else {
    n <- 0
    while(T) {
      r2 <- get_dice()
      n <- n + 1
      if (r2 == 7) {
        fim <- F
        break
      } 
      if (r2 == r1) {
        fim <- T
        break
      }
    }
  }
  return(cbind.data.frame(fim, n))
}

# testando a funcao
get_game()
##     fim n
## 1 FALSE 1
# gerando algumas partidas

N <- seq(10, 20010, by = 500)

cores <- parallel::detectCores()
cl <- makeSOCKcluster(cores)
registerDoSNOW(cl)

res <- foreach(i = 1:length(N), .combine = 'list', .multicombine = T) %:%
  foreach(j = 1:N[i], .combine = 'rbind.data.frame') %dopar% {
    get_game()
  }
length(res)
## [1] 41
names(res) <- N
resultados <- bind_rows(res, .id =  'N')
resultados$N <- as.numeric(resultados$N)
resultados <- tibble(resultados)

# proporcao de ganhos
tmp <- resultados %>% 
  group_by(N) %>% 
  summarise(prop = mean(fim)) %>% 
  arrange(N)
## `summarise()` ungrouping output (override with `.groups` argument)
tmp
## # A tibble: 41 x 2
##        N  prop
##    <dbl> <dbl>
##  1    10 0.6  
##  2   510 0.482
##  3  1010 0.5  
##  4  1510 0.492
##  5  2010 0.513
##  6  2510 0.480
##  7  3010 0.502
##  8  3510 0.491
##  9  4010 0.495
## 10  4510 0.491
## # … with 31 more rows
ggplot(tmp, aes(x = N, y = prop, group = 1)) +
  geom_line(alpha = I(.5)) +
  geom_point() +
  geom_hline(yintercept = .49, col = 'tomato') +
  xlab('Jogo simulado com N jogos') +
  ylab('Proporção de vezes em que se ganha') +
  labs(title = 'Convergência para o resultado da solução analítica')+
  theme_minimal()

# Quando no primeiro lancamento nao tirar 2, 3, 7, 11 ou 12
# entao continuar jogando ate sair 7 ou o primeiro resultado
# Qual a quantidade de jogos necessarios ate ganhar e/ou perder?

# incondicional
tmp <- resultados %>% 
  group_by(N) %>% 
  summarise(n_media = mean(n, na.rm = T),
            n_var = var(n, na.rm = T)) %>% 
  arrange(N)
## `summarise()` ungrouping output (override with `.groups` argument)
tmp
## # A tibble: 41 x 3
##        N n_media n_var
##    <dbl>   <dbl> <dbl>
##  1    10    3.5   5.67
##  2   510    3.72  8.97
##  3  1010    3.66  9.21
##  4  1510    3.54  8.33
##  5  2010    3.66 10.2 
##  6  2510    3.52  9.80
##  7  3010    3.56  9.50
##  8  3510    3.64  9.95
##  9  4010    3.48  8.59
## 10  4510    3.48  8.86
## # … with 31 more rows
ggplot(tmp, aes(x = N, y = n_media, group = 1)) +
  geom_line(alpha = I(.5)) +
  geom_point() +
  xlab('Jogo simulado com N jogos') +
  ylab('Média de jogos') +
  labs(title = 'Número médio de vezes em que joga até ganhar ou perder')+
  theme_minimal()

# criando animacao
p <- resultados %>% 
  na.omit() %>% 
  ggplot(aes(y = n, fill = fim)) +
  geom_bar(position = 'identity') +
  facet_wrap(~ fim) +
  ylab('') +
  xlab('') +
  labs(title = 'Número de lançamentos de dados até ganhar ou perder.',
       subtitle = '(caso o primeiro resultado não seja 2, 3, 7, 11 ou 12)') +
  coord_flip() +
  theme_minimal() +
  theme(legend.position = 'none')
p

p + 
  transition_time(N) +
  labs(title = "N: {frame_time}")

# tempo de processamento
Sys.time() - t0
## Time difference of 10.70034 mins