Skip to content

Commit 5391eff

Browse files
committed
Refactor to R package (v0.1.0)
1 parent 27cdcae commit 5391eff

62 files changed

Lines changed: 2758 additions & 1946 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.Rbuildignore

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Development files
2+
^.*\.Rproj$
3+
^\.Rproj\.user$
4+
^\.Rhistory$
5+
^\.RData$
6+
^\.Ruserdata$
7+
8+
# Git
9+
^\.git$
10+
^\.github$
11+
^\.gitignore$
12+
13+
# Documentation extras
14+
^README\.Rmd$
15+
^LICENSE\.md$
16+
^cran-comments\.md$
17+
^CRAN-SUBMISSION$
18+
^_pkgdown\.yml$
19+
^docs$
20+
^pkgdown$
21+
22+
# Development
23+
^data$
24+
25+
# IDE
26+
^\.vscode$
27+
28+
# CI/CD
29+
^\.gitlab-ci\.yml$
30+
^\.travis\.yml$
31+
^codecov\.yml$
32+
^appveyor\.yml$
33+
34+
# Misc
35+
^preview\.png$

.github/workflows/R-CMD-check.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
on:
2+
push:
3+
branches: [main, master]
4+
pull_request:
5+
branches: [main, master]
6+
7+
name: R-CMD-check
8+
9+
jobs:
10+
R-CMD-check:
11+
runs-on: ${{ matrix.config.os }}
12+
13+
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
14+
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
config:
19+
- { os: macos-latest, r: "release" }
20+
- { os: windows-latest, r: "release" }
21+
- { os: ubuntu-latest, r: "devel", http-user-agent: "release" }
22+
- { os: ubuntu-latest, r: "release" }
23+
- { os: ubuntu-latest, r: "oldrel-1" }
24+
25+
env:
26+
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
27+
R_KEEP_PKG_SOURCE: yes
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- uses: r-lib/actions/setup-pandoc@v2
33+
34+
- uses: r-lib/actions/setup-r@v2
35+
with:
36+
r-version: ${{ matrix.config.r }}
37+
http-user-agent: ${{ matrix.config.http-user-agent }}
38+
use-public-rspm: true
39+
40+
- uses: r-lib/actions/setup-r-dependencies@v2
41+
with:
42+
extra-packages: any::rcmdcheck
43+
needs: check
44+
45+
- uses: r-lib/actions/check-r-package@v2
46+
with:
47+
upload-snapshots: true

.gitignore

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.Rhistory
44
.RData
55
.Ruserdata
6-
*.Rproj
6+
77

88
# RStudio
99
.Renviron
@@ -14,24 +14,10 @@
1414
rsconnect/
1515
*_cache/
1616

17-
# Package specific
17+
# Package build
1818
*.tar.gz
1919
*.Rcheck/
2020

21-
# Test results
22-
test-results.xml
23-
24-
# Experiment resources
25-
droptoken.rds
26-
app/www/*
27-
!app/www/.gitkeep
28-
29-
# Data
30-
data/raw/*
31-
!data/raw/.gitkeep
32-
data/processed/*
33-
!data/processed/.gitkeep
34-
3521
# Logs
3622
*.log
3723
logs/
@@ -48,6 +34,3 @@ Thumbs.db
4834
.vscode/
4935
*.sublime-project
5036
*.sublime-workspace
51-
52-
# Archive
53-
archive/

DESCRIPTION

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
Package: dcelab
2+
Title: Create and Deploy Discrete Choice Experiments
3+
Version: 0.1.0
4+
Authors@R: c(
5+
person("Przemyslaw", "Marcowski", , "p.marcowski@gmail.com", role = c("aut", "cre"),
6+
comment = c(ORCID = "0000-0001-7342-6561")),
7+
person("Jakub", "Krawiec", , "krawiecjm@gmail.com", role = "aut"))
8+
Description: Framework for creating, configuring, and deploying Discrete
9+
Choice Experiments (DCE). Scaffolds experiment directories with
10+
configurable Shiny applications, generates D-efficient experimental
11+
designs using 'idefix', validates configurations, and handles
12+
deployment to 'shinyapps.io' with response data storage to AWS S3.
13+
License: GPL-3
14+
URL: https://github.com/pmarcowski/dcelab
15+
BugReports: https://github.com/pmarcowski/dcelab/issues
16+
Depends:
17+
R (>= 4.0.0)
18+
Imports:
19+
aws.s3,
20+
checkmate,
21+
cli,
22+
idefix,
23+
MASS,
24+
rsconnect,
25+
shiny,
26+
shinyjs,
27+
withr,
28+
yaml
29+
Suggests:
30+
googleCloudStorageR,
31+
googlesheets4,
32+
mockery,
33+
rdrop2,
34+
testthat (>= 3.0.0)
35+
Config/testthat/edition: 3
36+
Encoding: UTF-8
37+
Roxygen: list(markdown = TRUE)
38+
RoxygenNote: 7.3.3

NAMESPACE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
export(create_experiment)
4+
export(deploy_experiment)
5+
export(prepare_experiment)
6+
export(run_demo)
7+
export(run_experiment)
8+
export(save_experiment_data)
9+
export(save_to_dropbox)
10+
export(save_to_gcs)
11+
export(save_to_gsheets)
12+
export(save_to_local)
13+
export(save_to_s3)
14+
export(validate_config)
15+
export(validate_custom_attributes)
16+
export(validate_storage_config)
17+
import(shinyjs)
18+
importFrom(shiny,runApp)
19+
importFrom(stats,setNames)
20+
importFrom(utils,browseURL)
21+
importFrom(utils,read.csv)
22+
importFrom(utils,write.table)

NEWS.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# dcelab 0.1.0
2+
3+
Initial release.
4+
5+
## Features
6+
7+
* **Scaffolding**: `create_experiment()` creates complete experiment directories from templates
8+
* **D-efficient designs**: `prepare_experiment()` generates optimal choice designs using idefix
9+
* **Local testing**: `run_experiment()` launches experiments locally
10+
* **Cloud deployment**: `deploy_experiment()` deploys to shinyapps.io
11+
* **Demo mode**: `run_demo()` for instant demonstration
12+
* **Custom attributes**: Support for custom display functions (images, dynamic content)
13+
14+
## Storage Providers
15+
16+
* Local file storage (default)
17+
* AWS S3
18+
* Google Sheets
19+
* Google Cloud Storage
20+
* Dropbox
21+
22+
## Workflow
23+
24+
```r
25+
library(dcelab)
26+
create_experiment("my_study")
27+
# Edit config.yaml and attributes.csv
28+
prepare_experiment("my_study")
29+
run_experiment("my_study")
30+
deploy_experiment("my_study")
31+
```

R/create.R

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#' Create New DCE Experiment
2+
#'
3+
#' Scaffolds a new experiment directory with all necessary template files.
4+
#' Creates a complete, ready-to-configure experiment structure.
5+
#'
6+
#' @param path Character. Path where the experiment directory will be created.
7+
#' @param open Logical. Open the directory in file explorer after creation.
8+
#' Defaults to `TRUE` in interactive sessions.
9+
#'
10+
#' @return Invisibly returns the path to the created experiment directory.
11+
#'
12+
#' @details
13+
#' Creates an experiment directory with the following structure:
14+
#' ```
15+
#' path/
16+
#' ├── app.R # Shiny application
17+
#' ├── utils.R # App utility functions
18+
#' ├── config.yaml # Experiment configuration
19+
#' ├── attributes.csv # Attribute definitions
20+
#' ├── intro.txt # Introduction text
21+
#' ├── outro.txt # Closing text
22+
#' └── www/ # Static assets directory
23+
#' ```
24+
#'
25+
#' After creation, edit `config.yaml` and `attributes.csv` to define your
26+
#' experiment, then run [prepare_experiment()] to generate the design.
27+
#'
28+
#' @seealso [prepare_experiment()], [run_experiment()], [deploy_experiment()]
29+
#'
30+
#' @examples
31+
#' \dontrun{
32+
#' # Create a new experiment
33+
#' create_experiment("my_study")
34+
#'
35+
#' # Edit config.yaml and attributes.csv, then:
36+
#' prepare_experiment("my_study")
37+
#' run_experiment("my_study")
38+
#' }
39+
#'
40+
#' @export
41+
create_experiment <- function(path, open = interactive()) {
42+
# Validate path
43+
checkmate::assert_character(path, len = 1, min.chars = 1)
44+
45+
# Check if directory already exists
46+
47+
if (dir.exists(path)) {
48+
cli::cli_abort("Directory already exists: {.path {path}}")
49+
}
50+
51+
# Get template directory
52+
53+
template_dir <- system.file("templates", package = "dcelab")
54+
if (template_dir == "") {
55+
cli::cli_abort(
56+
"Template directory not found. Is dcelab installed correctly?"
57+
)
58+
}
59+
60+
# Create experiment directory
61+
dir.create(path, recursive = TRUE, showWarnings = FALSE)
62+
dir.create(file.path(path, "www"), showWarnings = FALSE)
63+
64+
# Copy template files
65+
template_files <- list.files(template_dir, full.names = TRUE)
66+
file.copy(template_files, path, recursive = TRUE)
67+
68+
cli::cli_alert_success("Created experiment at {.path {path}}")
69+
cli::cli_bullets(c(
70+
"i" = "Next steps:",
71+
" " = "1. Edit {.file config.yaml} to configure your experiment",
72+
" " = "2. Edit {.file attributes.csv} to define attributes and levels",
73+
" " = "3. Run {.code prepare_experiment(\"{path}\")} to generate design",
74+
" " = "4. Run {.code run_experiment(\"{path}\")} to test locally"
75+
))
76+
77+
# Open directory if requested
78+
79+
if (open && interactive()) {
80+
utils::browseURL(path)
81+
}
82+
83+
invisible(path)
84+
}

R/dcelab-package.R

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#' @keywords internal
2+
"_PACKAGE"
3+
4+
#' dcelab: Create and Deploy Discrete Choice Experiments
5+
#'
6+
#' Framework for creating, configuring, and deploying Discrete Choice
7+
#' Experiments (DCE). Provides a streamlined workflow for scaffolding
8+
#' experiment directories, generating D-efficient designs, and deploying
9+
#' to shinyapps.io.
10+
#'
11+
#' @section Workflow:
12+
#' The typical workflow consists of four steps:
13+
#' 1. `create_experiment()` - Scaffold a new experiment directory
14+
#' 2. Edit configuration files (config.yaml, attributes.csv)
15+
#' 3. `prepare_experiment()` - Validate and generate design
16+
#' 4. `run_experiment()` or `deploy_experiment()` - Test or deploy
17+
#'
18+
#' @section Main functions:
19+
#' * [create_experiment()] - Create new experiment from template
20+
#' * [prepare_experiment()] - Prepare experiment for deployment
21+
#' * [run_experiment()] - Run experiment locally
22+
#' * [deploy_experiment()] - Deploy to shinyapps.io
23+
#'
24+
#' @name dcelab-package
25+
#' @aliases dcelab
26+
NULL
27+
28+
## usethis namespace: start
29+
#' @importFrom stats setNames
30+
#' @importFrom utils read.csv write.table browseURL
31+
#' @importFrom shiny runApp
32+
#' @import shinyjs
33+
## usethis namespace: end
34+
NULL

0 commit comments

Comments
 (0)