---
title: "OpenFAIR Example"
runtime: shiny
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
    source_code: embed
    navbar:
      - { title: "About", href: "https://evaluator.severski.net", align: right }
---

```{r setup, include=FALSE}
library(extrafont)
library(evaluator)
library(flexdashboard)
library(ggplot2)
library(mc2d)
library(shiny)
library(scales)
library(dplyr)
```

```{r common_functions, include=FALSE}
```

```{r core_functions, include=FALSE}
# determine the proper base font to use for graphs
basefont <- get_base_fontfamily()

values <- reactiveValues() 

values$N <- 10000

observeEvent(input$runmodel, {
	
	values$N <- input$N

	TEFestimate <- data.frame(L = input$tefl, ML = input$tefml, H = input$tefh,
	                          CONF = input$tefconf)
	TCestimate <- data.frame(L = input$tcapl, ML = input$tcapml, H = input$tcaph,
	                         CONF = input$tcapconf)
	DIFFestimate <- data.frame(L = input$csl, ML = input$csml, H = input$csh, 
	                           CONF = input$csconf)
  LMestimate <- data.frame(L = input$lml, ML = input$lmml, H = input$lmh, 
                           CONF = input$lmconf)
	
	LMsamples <- function(x){
	  return(sum(rpert(x, LMestimate$L, LMestimate$ML, LMestimate$H, 
	                   shape = LMestimate$CONF) ))
			}
	TEFsamples <- rpert(values$N, TEFestimate$L, TEFestimate$ML, TEFestimate$H, 
	                    shape = TEFestimate$CONF)
	TCsamples <- rpert(values$N, TCestimate$L, TCestimate$ML, TCestimate$H, 
	                   shape = TCestimate$CONF)
	DIFFsamples <- rpert(values$N, DIFFestimate$L, DIFFestimate$ML, 
	                     DIFFestimate$H, shape = DIFFestimate$CONF)
	
	VULNsamples <- TCsamples > DIFFsamples
	LEF <- TEFsamples[VULNsamples]
		
	values$ALEsamples <- sapply(LEF, LMsamples)
	values$VAR <- quantile(values$ALEsamples, probs = (0.95))
	values$VULNsamples <- VULNsamples
			
})
```

Scenario Parameters {.sidebar data-width=400}
-----------------------------------------------------------------------

### TEF

Frequency of action by the actor.

```{r input_tef}
fillRow(height = 50,
  numericInput("tefl", "Min:", 10, min = 0, max = 100),
  numericInput("tefml", "ML:", 20, min = 0, max = 100),
  numericInput("tefh", "Max:", 100, min = 0, max = 100),
  numericInput("tefconf", "Conf:", 1, min = 1, max = 5)
)
```

### TCAP

Capabilities of the threat actor.

```{r input_tcap}
fillRow(height = 50,
  numericInput("tcapl", "Min:", 20, min = 0, max = 100),
  numericInput("tcapml", "ML:", 30, min = 0, max = 100),
  numericInput("tcaph", "Max:", 70, min = 0, max = 100),
  numericInput("tcapconf", "Conf:", 1, min = 1, max = 5)
)
```

### DIFF

Difficulty presented by the controls.

```{r input_diff}
fillRow(height = 50,
  numericInput("csl", "Min:", 40, min = 0, max = 100),
  numericInput("csml", "ML:", 50, min = 0, max = 100),
  numericInput("csh", "Max:", 60, min = 0, max = 100),
  numericInput("csconf", "Conf:", 2, min = 1, max = 5)
)
```

### LM

Loss magnitude

```{r input_lm}
fillRow(height = 50,
  numericInput("lml", "Min:", 100, min = 0),
  numericInput("lmml", "ML:", 500, min = 0),
  numericInput("lmh", "Max:", 10000, min = 0),
  numericInput("lmconf", "Conf:", 1, min = 1, max = 5)
)
```

### Params {.no-title}

```{r}
numericInput("N", "# Iterations:", 10000, min = 1000, max = 100000, step = 1000)
actionButton("runmodel", "Run Model")
```

Results {.tabset data-width=600}
----------------------------------------------------------------------

### Loss Distribution

```{r plot_distribution}
renderPlot({
	if (input$runmodel != 0) {
		ALEsamples <- values$ALEsamples 
		gg <- ggplot(data.frame(ALEsamples), aes(x = ALEsamples))
		gg <- gg + geom_histogram(binwidth = diff(range(ALEsamples)/50), 
		                          aes(y = ..density..), 
		                          color = "black", 
		                          fill = "white")
		gg <- gg + geom_density(fill = "steelblue", alpha = 1/3)
		gg <- gg + scale_x_continuous(labels = comma)
		gg <- gg + labs(x = "Annual Expected Losses")
		gg <- gg + theme_evaluator(base_family = basefont)
		print(gg)
	}
})
```

### Details

#### Loss Summary {.no-title} 

```{r detail1}
renderPrint({
  if (input$runmodel != 0) {
  	print(summary(values$ALEsamples))
	}
})
```	

#### 95% Value at Risk {.no-title} 

```{r detail2}
renderPrint({
  if (input$runmodel != 0) {
  	print(paste0("Losses at 95th percentile are $", 
  	             format(values$VAR, nsmall = 2, big.mark = ",")
  	             ))
	}
})
```

#### Loss Samples
```{r detail3}
DT::renderDataTable(
  if (input$runmodel != 0) {
    dat <- data.frame(Losses = values$ALEsamples) %>% arrange(desc(Losses)) %>% 
      transmute(Losses = scales::dollar(Losses))
    DT::datatable(dat, rownames = FALSE)
  }
)
```

### Event Distribution

```{r loss_events}
renderPlot({
  if (input$runmodel != 0) {
    VULNsamples <- as.logical(values$VULNsamples)
    VULNsamples <- data.frame(losses = (sum(VULNsamples) / length(VULNsamples)),
                              avoided = (length(VULNsamples) - 
                                           sum(VULNsamples)) / 
                                length(VULNsamples))
    gg <- ggplot(tidyr::gather(VULNsamples), aes(x=key, y=value)) + 
      geom_col(fill = "steelblue") +
      labs(x="Event Type", y="Percent") + 
      scale_y_continuous(labels = scales::percent_format()) +
      theme_evaluator(base_family = evaluator::get_base_fontfamily())
    print(gg)
  }
})
```
