Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
c096dfd
Merge pull request #2 from ds4owd-dev/dev
massarin Jul 9, 2025
41fc139
Merge pull request #3 from ds4owd-dev/dev
massarin Jul 9, 2025
021fc39
Merge pull request #4 from ds4owd-dev/dev
massarin Jul 9, 2025
dab68eb
Merge pull request #6 from ds4owd-dev/dev
massarin Jul 14, 2025
03eaba8
Merge pull request #7 from ds4owd-dev/dev
massarin Aug 18, 2025
e9f2dff
Merge pull request #8 from ds4owd-dev/dev
massarin Aug 18, 2025
4eb7f5c
Merge pull request #9 from ds4owd-dev/dev
massarin Aug 18, 2025
2360830
Merge pull request #11 from ds4owd-dev/dev
massarin Sep 8, 2025
69df035
Merge pull request #12 from ds4owd-dev/dev
massarin Sep 9, 2025
77f208d
Merge pull request #13 from ds4owd-dev/dev
massarin Sep 9, 2025
448b358
Merge pull request #14 from ds4owd-dev/dev
massarin Sep 9, 2025
6eb85af
Merge pull request #15 from ds4owd-dev/dev
massarin Sep 10, 2025
1bcdad8
update question and answer options
larnsce Sep 10, 2025
134b5e4
complete quiz
larnsce Sep 10, 2025
dddd13a
update config
larnsce Sep 10, 2025
0bc448e
fix error
larnsce Sep 10, 2025
fe71337
update link
larnsce Sep 10, 2025
7af9774
update text
larnsce Sep 10, 2025
ff59bb1
update ID
larnsce Sep 10, 2025
3c46402
chore: update github username with latest roaster
massarin Sep 11, 2025
b2d8e5d
Merge pull request #2 from ds4owd-dev/dev
massarin Sep 11, 2025
1e912e5
fix: broken link, https:/ was repeated
massarin Sep 11, 2025
c34eac9
Merge pull request #3 from ds4owd-dev/dev
massarin Sep 11, 2025
224802c
update roster
larnsce Sep 12, 2025
d377098
Add options
larnsce Sep 12, 2025
05a5c3f
add CLAUDE.md
larnsce Sep 12, 2025
e861e8f
initial commit
larnsce Sep 12, 2025
9cb0073
draft map exercise
larnsce Sep 12, 2025
661765a
add participants summary
larnsce Sep 12, 2025
77a1a1c
simplify map
larnsce Sep 12, 2025
f21b6c7
make map interactive
larnsce Sep 12, 2025
3a78f91
add gradethis
larnsce Sep 13, 2025
1ea75cd
do not display quiz 2
larnsce Sep 16, 2025
a7489af
update usernames
larnsce Sep 16, 2025
cf939d0
Merge pull request #4 from ds4owd-dev/dev
larnsce Sep 16, 2025
1ca7053
add sentence
larnsce Sep 17, 2025
e5f6cbb
add section
larnsce Sep 17, 2025
01aa594
update username
larnsce Sep 18, 2025
74994ca
Add quiz for module 2
larnsce Sep 18, 2025
fb59b49
Merge pull request #5 from ds4owd-dev/dev
larnsce Sep 18, 2025
29c6c63
fix: #6, include libraries to DESCRIPTION > Imports
massarin Sep 18, 2025
161ada9
Merge pull request #7 from ds4owd-dev/dev
massarin Sep 18, 2025
1e92ab2
fix: bundle only required files for each quiz
massarin Sep 18, 2025
bdb8744
fix: Creates a temporary directory
massarin Sep 18, 2025
bf228d2
fix: remove here::here, refactor data pathing
massarin Sep 18, 2025
1c4619b
fix: deploy from separate dirs, remove setwd and temp
massarin Sep 19, 2025
bd9e91a
fix: add show logs
massarin Sep 19, 2025
1e5575b
fix: readme modules path
massarin Sep 19, 2025
c424377
fix: add missing rnaturalearthdata dependency
massarin Sep 19, 2025
368355d
fix: add fallback
massarin Sep 19, 2025
797f8f8
fix: add remotes, add slow warning, remove second loading of world map
massarin Sep 19, 2025
c8179b0
fix: remove plotly
massarin Sep 19, 2025
6cb30ee
fix: remove plotly
massarin Sep 19, 2025
96ae00b
fix: remove plotly
massarin Sep 19, 2025
bddede2
Merge pull request #8 from ds4owd-dev/dev
massarin Sep 19, 2025
421cb37
update usernames
larnsce Sep 22, 2025
9e3a254
feat: move common module files to common modules/common to have one s…
massarin Sep 23, 2025
7f26e4f
Merge branch 'main' of https://github.com/ds4owd-dev/ds4owd-002-quiz …
massarin Sep 23, 2025
9644519
Merge branch 'dev' of https://github.com/ds4owd-dev/ds4owd-002-quiz i…
massarin Sep 23, 2025
e0592d8
fix: fix merge
massarin Sep 23, 2025
bec91c7
feat: better submission UI
massarin Sep 24, 2025
7cad714
update usernames
Sep 24, 2025
754de59
fix: submission to form
massarin Sep 24, 2025
ed28fa8
Merge branch 'dev' of https://github.com/ds4owd-dev/ds4owd-002-quiz i…
massarin Sep 24, 2025
2ec6625
chore: update local deployment
massarin Sep 24, 2025
a4a971d
initial commit
Sep 24, 2025
e29ebec
add quiz 3
Sep 25, 2025
f242038
fix: remove additional section
massarin Sep 25, 2025
f768d49
feat: add live quiz checker link
massarin Sep 25, 2025
0462b9e
initial commit
Oct 2, 2025
ae79145
Merge branch 'dev' of https://github.com/ds4owd-dev/ds4owd-002-quiz i…
Oct 2, 2025
4ba1dad
add forcats package dependency
Oct 2, 2025
b872de8
remove forcats dependency completely
Oct 2, 2025
7ec6c2c
fix: child Rmds are copied in quiz repo at deploy by build.R
massarin Oct 3, 2025
d728e92
update README
Oct 28, 2025
5ca34ab
prepare quiz 5
Oct 28, 2025
5f5d2ed
Merge branch 'dev' of https://github.com/ds4owd-dev/ds4owd-002-quiz i…
Oct 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ docs/
!docs/*.md
*.dcf
*.html
*.png

# renv - using DESCRIPTION for dependencies instead
renv/
Expand All @@ -20,4 +21,6 @@ rsconnect/

venv/

legacy/
legacy/

CLAUDE.md
14 changes: 12 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ URL: https://github.com/ds4owd-dev/quiz,
https://ds4owd-dev.github.io/quiz/
BugReports: https://github.com/ds4owd-dev/quiz/issues
Imports:
remotes,
learnr,
dplyr,
gapminder,
Expand All @@ -24,9 +25,18 @@ Imports:
shiny,
bslib,
rsconnect,
yaml
yaml,
countrycode,
ggplot2,
here,
palmerpenguins,
readr,
rnaturalearth,
rnaturalearthdata,
sf
Suggests:
pkgdown
Remotes:
rstudio/gradethis,
rundel/learnrhash
rundel/learnrhash,
ropensci/rnaturalearthdata
58 changes: 40 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@

This directory contains interactive learnr quizzes for the openwashdata course and a landing page to access them.

**Live Demo**: https://hjj91u-nicolo-massari.shinyapps.io/openwashdata-quiz-hub/
**Live Demo**: https://u4x6xe-lars-sch0bitz.shinyapps.io/ds4owd-002-quiz/

## Structure

- `app.R` - Quiz landing page that automatically displays all configured quizzes
- `build.R` - Deployment script with helper functions for automated deployment
- `config.R` - Shared configuration file defining all available quizzes
- `modules/` - Directory containing all quiz files
- `md-01-quiz.Rmd` - Module 1 quiz on Quarto basics (learnr tutorial)
- `_github_username.Rmd` - Reusable component for GitHub username input with CSV data
- `_submission.Rmd` - Reusable component for quiz submission
- `github_usernames.csv` - Student GitHub username database
- Additional quiz files can be added as `md-XX-quiz.Rmd`
- `modules/` - Directory containing individual quiz directories
- `md-01-quiz/` - Module 1 quiz directory with all required files
- `md-02-quiz/` - Module 2 quiz directory with all required files
- Each quiz directory contains:
- `md-XX-quiz.Rmd` - Main quiz file (learnr tutorial)
- `_github_username.Rmd` - Reusable component for GitHub username input
- `_participation.Rmd` - Reusable component for participation tracking
- `_submission.Rmd` - Reusable component for quiz submission
- `github_usernames.csv` - Student GitHub username database
- `data/` - Quiz-specific data files (if needed)

## Required Packages

Expand Down Expand Up @@ -49,6 +53,7 @@ Replace `your-account-name`, `YOUR-TOKEN-HERE`, and `YOUR-SECRET-HERE` with your
The quizzes now include automatic submission to Google Forms for tracking student progress:

### Features

- **GitHub username collection**: Students enter their GitHub username at the start
- **Learnrhash generation**: Quiz responses are encoded using learnrhash
- **Automatic submission**: Results are submitted to Google Form via POST request
Expand All @@ -61,6 +66,7 @@ To connect quizzes to your own Google Form, update the configuration in `modules
#### 0. Google Form Structure

Your Google Form should have exactly 3 questions:

1. **Tutorial/Module ID** (text field)
2. **GitHub username** (text field)
3. **Learnrhash** (long text field for quiz results)
Expand Down Expand Up @@ -91,6 +97,7 @@ learnrhash_entry_id <- "entry.YOUR-LEARNRHASH-ID" # For quiz results
```

#### Example Current Setup

- **Form URL**: https://docs.google.com/forms/d/e/1FAIpQLScnw9R8wMU5SfFqNVXGeEkiIygLTB_Dc6jWBmbwEeHuekBDzg/formResponse
- **Entry IDs**:
- `entry.1169139257` - Module name (1st question)
Expand Down Expand Up @@ -129,6 +136,7 @@ Quizzes are automatically deployed to shinyapps.io via GitHub Actions when chang
#### How the CI/CD Workflow Works

The GitHub Action (`.github/workflows/deploy-quiz.yml`):
s
- **Triggers**: On pushes to `main`/`dev` branches or manual workflow dispatch
- **Environment**: Sets up R 4.3.2 with required packages from DESCRIPTION
- **Authentication**: Uses repository secrets to authenticate with shinyapps.io
Expand All @@ -145,44 +153,55 @@ source("build.R")
```

The deployment system features:
- **Automatic file bundling**: CSV files and dependencies are automatically included
- **Direct module deployment**: Deploys directly from module directories (no temp files)
- **Self-contained modules**: Each quiz directory contains all required files
- **Streamlined process**: One script deploys everything configured in `config.R`

## Adding New Quizzes

The system now uses automatic configuration - adding a new quiz is simple:
The system uses a modular directory structure - adding a new quiz requires creating a complete directory:

### 1. Create the Quiz Directory

### 1. Create the Quiz File
Create a new directory `modules/md-XX-quiz/` and add all required files:

Create `modules/md-02-quiz.Rmd` with the standardized YAML header:
```bash
mkdir modules/md-03-quiz
cp modules/md-01-quiz/_*.Rmd modules/md-01-quiz/github_usernames.csv modules/md-03-quiz/
```

### 2. Create the Quiz File

Create `modules/md-XX-quiz/md-XX-quiz.Rmd` with the standardized YAML header:

```yaml
---
title: "Module 2: Your Title"
title: "Module 3: Your Title"
output: learnr::tutorial
runtime: shiny_prerendered
description: "Your quiz description"
tutorial:
id: "module2-your-id"
id: "md-03-quiz"
---
```

Add your quiz content following the existing pattern, including:
- GitHub username collection: `{r github-username, child='_github_username.Rmd'}`
- Quiz submission: `{r submission-section, child='_submission.Rmd'}`

### 2. Update Configuration
### 3. Update Configuration

Edit `config.R` to include your new quiz:

```r
quiz_names <- c(
"md-01-quiz",
"md-02-quiz" # Add new quiz here
"md-02-quiz",
"md-03-quiz" # Add new quiz here
)
```

### 3. Deploy
### 4. Deploy

Run the build script to deploy everything:

Expand All @@ -199,8 +218,11 @@ This will:
### Test Individual Quizzes

```r
# Test a quiz locally
rmarkdown::run("modules/md-01-quiz.Rmd")
source("local_build.R")

# Run a specific quiz interactively
run_quiz("md-01-quiz")
run_quiz("md-02-quiz")
```

### Test Landing Page
Expand Down
16 changes: 9 additions & 7 deletions app.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ source("config.R")

# Function to extract quiz metadata from Rmd files
extract_quiz_metadata <- function(quiz_name) {
rmd_path <- file.path("modules", paste0(quiz_name, ".Rmd"))
rmd_path <- file.path("modules", quiz_name, paste0(quiz_name, ".Rmd"))

if (!file.exists(rmd_path)) {
return(NULL)
Expand Down Expand Up @@ -60,7 +60,7 @@ quizzes <- generate_quiz_list(quiz_names)

# UI
ui <- page_navbar(
title = "openwashdata Quizzes",
title = "ds4owd-002 quiz",
theme = bs_theme(bootswatch = "cosmo"),

nav_panel(
Expand All @@ -69,8 +69,9 @@ ui <- page_navbar(
class = "container mt-5",
div(
class = "text-center mb-5",
h1("openwashdata Course Quizzes"),
p(class = "lead", "Interactive tutorials to test your knowledge")
h1("data science for openwashdata - quiz"),
p(class = "lead", "Interactive tutorials to test your knowledge."),
p(class = "lead text-warning fw-bold", "For successful completion of the course, you need to complete the quizzes for each module."),
),

div(
Expand Down Expand Up @@ -118,15 +119,15 @@ ui <- page_navbar(
div(
class = "col-md-8",
h2("About These Quizzes"),
p("These interactive quizzes are designed to help you learn and practice concepts from the openwashdata course."),
p("These interactive quizzes are designed to help you learn and practice concepts from the ds4owd course. They are required to be completed for each module of the course."),

h3("Features"),
tags$ul(
tags$li("Interactive R code exercises"),
tags$li("Immediate feedback on your answers"),
tags$li("Hints and solutions available"),
tags$li("Progress tracking within each quiz"),
tags$li("Automatic grading with gradethis")
tags$li("Automatic grading")
),

h3("How to Use"),
Expand All @@ -136,7 +137,8 @@ ui <- page_navbar(
tags$li("Work through the questions at your own pace"),
tags$li("Run code in the interactive exercises"),
tags$li("Use hints if you get stuck"),
tags$li("Check your solutions for immediate feedback")
tags$li("Check your solutions for immediate feedback"),
tags$li("Ensure to submit the Quiz with your GitHub username")
),

h3("Technical Requirements"),
Expand Down
34 changes: 32 additions & 2 deletions build.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,43 @@ source("config.R")
# HELPER

deploy_quiz <- function(module_name) {
module_path <- paste0(file.path("modules", module_name), ".Rmd")
module_dir <- file.path("modules", module_name)
rmd_file <- file.path(module_dir, paste0(module_name, ".Rmd"))

if (!file.exists(rmd_file)) {
stop("Quiz file not found: ", rmd_file)
}

# Copy all common files to module directory
common_files <- list.files(
"modules/common",
full.names = TRUE,
recursive = TRUE
)
copied_files <- character(0)
for (file in common_files) {
if (file.info(file)$isdir == FALSE) {
dest_file <- file.path(module_dir, basename(file))
file.copy(file, dest_file, overwrite = TRUE)
copied_files <- c(copied_files, dest_file)
}
}

# Deploy directly from module directory
rsconnect::deployDoc(
doc = module_path,
doc = rmd_file,
appName = module_name,
forceUpdate = TRUE,
logLevel = "verbose"
)
rsconnect::showLogs()

# Clean up: delete copied common files after deployment
for (file in copied_files) {
if (file.exists(file)) {
file.remove(file)
}
}
}


Expand Down
12 changes: 7 additions & 5 deletions config.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@

# List of quiz modules to deploy and display
quiz_names <- c(
"md-01-quiz"
"md-01-quiz",
"md-02-quiz",
"md-03-quiz",
"md-04-quiz",
"md-05-quiz"
# Add new quizzes here:
# "md-02-quiz",
# "md-03-quiz"
)

# Base URL for deployed quizzes
base_url <- "https://hjj91u-nicolo-massari.shinyapps.io/"
base_url <- "https://u4x6xe-lars-sch0bitz.shinyapps.io/"

# Main app configuration
main_app_name <- "openwashdata-quiz-hub"
main_app_name <- "ds4owd-002-quiz"

# in modules/_submission.Rmd
#
Expand Down
56 changes: 56 additions & 0 deletions local_build.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Load configuration
source("config.R")

# HELPER FUNCTIONS

run_quiz <- function(module_name) {
module_dir <- file.path("modules", module_name)
rmd_file <- file.path(module_dir, paste0(module_name, ".Rmd"))

if (!file.exists(rmd_file)) {
stop("Quiz file not found: ", rmd_file)
}

# Copy all common files to module directory
common_files <- list.files(
"modules/common",
full.names = TRUE,
recursive = TRUE
)
copied_files <- character(0)
for (file in common_files) {
if (file.info(file)$isdir == FALSE) {
dest_file <- file.path(module_dir, basename(file))
file.copy(file, dest_file, overwrite = TRUE)
copied_files <- c(copied_files, dest_file)
}
}

# Set working directory to module directory for running
current_dir <- getwd()
on.exit({
setwd(current_dir)
# Clean up: delete copied common files after running
for (file in copied_files) {
if (file.exists(file)) {
file.remove(file)
}
}
})
setwd(module_dir)

# Run the quiz interactively
cat("Running", module_name, "interactively...\n")
rmarkdown::run(paste0(module_name, ".Rmd"))
}

# QUIZ RUNNING

cat("Available quizzes to run:\n")
for (i in seq_along(quiz_names)) {
cat(i, ":", quiz_names[i], "\n")
}

cat("\nTo run a specific quiz, use:\n")
cat("run_quiz('quiz-name')\n")
cat("\nExample: run_quiz('md-01-quiz')\n")
9 changes: 0 additions & 9 deletions modules/_participation.Rmd

This file was deleted.

Loading
Loading