---
title: "Cookbook: Continuous Outcome, End to End"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Cookbook: Continuous Outcome, End to End}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
```

One complete, runnable script: design a two-arm experiment with a
continuous outcome, assign treatment, record responses, and run every
matched inference procedure. Every chunk executes when the vignette is
built; copy the whole thing into a session and it works. The other
cookbooks (`vignette("cookbook-incidence")`, `-count`, `-proportion`,
`-survival`, `-ordinal`) follow exactly this shape, differing only in the
response and the inference class.

The pattern is always the same four steps:

1. **construct a `Design`** for `n` subjects and a `response_type`;
2. **assign treatment** — all at once (fixed designs) or one subject at a
   time as they arrive (sequential designs);
3. **record responses**;
4. **construct an `Inference` class** on the completed design and call its
   methods — or hand the design to `InferenceSuite` to run every applicable
   procedure at once.

## Setup and a simulated population

EDI is not on CRAN yet, so `install.packages("EDI")` fails — install the
prebuilt binaries from R-universe instead (fallback: straight from GitHub;
the R package is the `R/EDI` subdirectory). Not evaluated here: the
vignette builds inside an already-installed package.

```{r install, eval = FALSE, purl = FALSE}
install.packages("EDI", repos = c("https://kapelner.r-universe.dev", "https://cloud.r-project.org"))
# or: remotes::install_github("kapelner/EDI", subdir = "R/EDI")
```

```{r setup}
library(EDI)
set.seed(20260916)

n = 60
X = data.frame(
  age  = round(rnorm(n, 45, 12)),
  bmi  = round(rnorm(n, 27, 4), 1),
  male = rbinom(n, 1, 0.5)
)
true_effect = 2.5
```

## A fixed design: everyone is known up front

`DesignFixedBernoulli` assigns each subject by an independent coin flip —
the simplest fixed design, and the one under which every inference method
is valid without caveat. Subjects are added all at once, assigned all at
once, and responses recorded all at once.

```{r fixed-design}
des = DesignFixedBernoulli$new(n = n, response_type = "continuous", verbose = FALSE)
des$add_all_subjects_to_experiment(X)
des$assign_w_to_all_subjects()
w = des$get_w()                                  # 0/1 treatment vector

y = 10 + true_effect * w + 0.1 * X$age - 0.3 * X$bmi + rnorm(n, sd = 3)
des$add_all_subject_responses(y)
```

## Inference: covariate-adjusted OLS

`InferenceContinOLS` regresses the response on treatment and the
covariates. Every inference class exposes the same core verbs: a point
estimate, an asymptotic (Wald) interval and p-value, a randomization test
that re-randomizes under the design's own mechanism, and — for fixed
designs — a nonparametric bootstrap.

```{r ols}
inf = InferenceContinOLS$new(des, verbose = FALSE)
inf$num_cores = 1L

inf$compute_estimate()
inf$compute_asymp_confidence_interval(alpha = 0.05)
inf$compute_asymp_two_sided_pval()
```

The randomization test uses no distributional assumption: it re-draws
treatment `r` times from the same design and compares the observed
statistic to that reference distribution. `set_seed()` makes the result
reproducible (see `vignette("reproducibility")`).

```{r ols-rand}
inf$set_seed(1)
inf$compute_rand_two_sided_pval(r = 200, show_progress = FALSE)
```

Bootstrap intervals resample subjects (the design's own resampling
structure — rows here; matched pairs for matched designs):

```{r ols-boot}
inf$set_seed(1)
inf$compute_bootstrap_confidence_interval(alpha = 0.05, B = 200, show_progress = FALSE)
```

## Everything at once: `InferenceSuite`

`InferenceSuite` discovers every inference class compatible with this
design and response type, runs each applicable procedure, and reports a
single Cauchy-combined p-value across them. With `screen = TRUE` it prints
the full results table — the one-call answer to "what does every valid
analysis say?" — and returns the same results as an object (`res`) for
programmatic use.

By default it runs *every* method each class supports, including the
resampling ones (randomization, bootstrap, Bayesian bootstrap, jackknife)
at their full default replicate counts — a few minutes per class, which is
exactly what you want for a real analysis but not inside a vignette that
rebuilds on every `R CMD check`. So this chunk restricts `methods` to the
asymptotic procedures (`"wald"`, `"score"`, `"lik_ratio"`; classes that
don't support one simply skip it) and sets a per-class time guard. Drop
the `methods` argument to get the complete report.

```{r suite}
suite = InferenceSuite$new(des)
res = suite$run_all_inference(screen = TRUE, plots = FALSE, num_cores = 1L,
                              methods = c("wald", "score", "lik_ratio"), max_secs_per_class = 15)
```

## A sequential design: subjects arrive one at a time

Most real trials enroll sequentially. `DesignSeqOneByOneKK21` — the
Kapelner–Krieger matching-on-the-fly design — decides each arrival's
treatment by trying to match it to an earlier unmatched subject on the
covariates (using the reservoir of unmatched subjects otherwise), so
covariate balance is built as the trial runs. The API changes only at
step 2: assign and record **per subject**.

```{r seq-design}
des_seq = DesignSeqOneByOneKK21$new(n = n, response_type = "continuous", verbose = FALSE)
for (i in seq_len(n)) {
  w_i = des_seq$add_one_subject_to_experiment_and_assign(X[i, , drop = FALSE])
  y_i = 10 + true_effect * w_i + 0.1 * X$age[i] - 0.3 * X$bmi[i] + rnorm(1, sd = 3)
  des_seq$add_one_subject_response(i, y_i)
}
```

The matched inference class for this design, `InferenceContinKKOLSIVWC`,
combines a within-pair estimate with the reservoir's estimate (inverse-
variance weighted). Note the nonparametric bootstrap is **not** offered on
sequential designs whose assignment depends on earlier subjects (row
resampling would not replicate the design); the randomization test, which
replays the design's actual mechanism, is the right tool here.

```{r seq-inference}
inf_seq = InferenceContinKKOLSIVWC$new(des_seq, verbose = FALSE)
inf_seq$num_cores = 1L
inf_seq$compute_estimate()
inf_seq$compute_asymp_confidence_interval(alpha = 0.05)
inf_seq$set_seed(1)
inf_seq$compute_rand_two_sided_pval(r = 200, show_progress = FALSE)
```

## Where to go next

- Which classes exist for which design × response: the
  [reference index](https://kapelner.github.io/EDI/reference/index.html).
- How the estimates were validated: `vignette("validation-evidence")`.
- Seeds, RNG streams, and parallel reproducibility:
  `vignette("reproducibility")`.
- Power and operating characteristics for a planned design:
  `SimulationFramework` (see its reference page's `\donttest{}` example).
