Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Very rough draft) of Google Classroom porting over example #648

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion manuscript/Book.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
1-Introduction.md
quiz_ch1.md
2-A-new-chapter.md
3-References.md
About-this-Course.md
About-the-Authors.md
About-this-Course.md
1 change: 1 addition & 0 deletions quiz_jsons/quiz_ch1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"question_info_df":[{"question":"First question to ask goes here. (Note- you need a question mark at end like this. Just one is required if using a question mark in your question field)?","question_type":"multiple_choice","shuffle_opt":true,"correct_answer":1,"_row":"First question to ask goes here. (Note- you need a question mark at end like this. Just one is required if using a question mark in your question field)?"},{"question":"Question example with just a question mark?","question_type":"multiple_choice","shuffle_opt":true,"correct_answer":1,"_row":"Question example with just a question mark?"},{"question":"Second question to ask goes here?","question_type":"multiple_choice","shuffle_opt":true,"correct_answer":1,"_row":"Second question to ask goes here?"},{"question":"A more complicated example. Note the question mark at the end of the options! Which of the following are correct","question_type":"multiple_choice","shuffle_opt":true,"correct_answer":1,"_row":"A more complicated example. Note the question mark at the end of the options! Which of the following are correct"},{"question":"A question in which the order of choices is important?","question_type":"multiple_choice","shuffle_opt":false,"correct_answer":4,"_row":"A question in which the order of choices is important?"}],"choice_vectors":[["One correct answer here marked with a \"C\"","Mandatory incorrect answers have an \"m\"","A second mandatory incorrect answer","An optional incorrect answer here marked with an \"o\"","A second optional incorrect answer here"],["One correct answer here marked with a \"C\"","Mandatory incorrect answers have an \"m\"","A second mandatory incorrect answer","An optional incorrect answer here marked with an \"o\"","A second optional incorrect answer here"],["A correct answer here!","Mandatory incorrect answers have an \"m\"","A second mandatory incorrect answer","An optional incorrect answer here marked with an \"o\"","A second optional incorrect answer here"],["All of the examples listed except 5","1, 3, and 5","1, 2, and 3","All of the examples except 1 and 5","All of the examples listed"],["The possible responses should be labeled a, b, c, etc","The correct answer has a capital letter, in this case \"D\" is correct","both a and b","All of the above will always be last choice in this question"]]}
7 changes: 7 additions & 0 deletions resources/course_units.tsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
md_name type url chapt_title full_urls
1-Introduction.md chapter introduction.html 1 Introduction https://jhudatascience.org/OTTR_Template/introduction.html
quiz_ch1.md quiz NA NA NA
2-A-new-chapter.md chapter a-new-chapter.html 2 A new chapter https://jhudatascience.org/OTTR_Template/a-new-chapter.html
3-References.md chapter references.html 3 References https://jhudatascience.org/OTTR_Template/references.html
About-the-Authors.md chapter about-the-authors.html About the Authors https://jhudatascience.org/OTTR_Template/about-the-authors.html
About-this-Course.md chapter index.html About this Course https://jhudatascience.org/OTTR_Template/index.html
121 changes: 121 additions & 0 deletions scripts/make_material_df.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env Rscript

# This script sets up a dataframe that has all the information for the
# quizzes, topics, materials, projects, and swirl modules and in what order they belong

# Written by Candace Savonen June 2023

if (!('devtools' %in% installed.packages())) {
# install.packages("remotes", repos = "http://cran.us.r-project.org")
}

if (!('optparse' %in% installed.packages())) {
# install.packages("optparse", repos = "http://cran.us.r-project.org")
}

# Find .git root directory
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))


library(optparse)
library(magrittr)

option_list <- list(
optparse::make_option(
c("--owner_id"),
type = "character",
default = NULL,
help = "Owner id",
),
optparse::make_option(
c("--course_name"),
type = "character",
default = NULL,
help = "Course name for this",
),
optparse::make_option(
c("--repo"),
type = "character",
default = NULL,
help = "GitHub repository name, e.g. jhudsl/OTTR_Template",
),
optparse::make_option(
c("--git_pat"),
type = "character",
default = NULL,
help = "GitHub personal access token",
),
optparse::make_option(
c("--output_dir"),
type = "character",
default = "resources/chapt_screen_images",
help = "Output directory where the chapter's screen images should be stored",
),
optparse::make_option(
c("--base_url"),
type = "character",
default = NULL,
help = "Output directory where the chapter's screen images should be stored",
),
optparse::make_option(
c("--make_book_txt"),
action = "store_true",
help = "Should book.txt file be made freshly?",
)
)

# Read the arguments passed
opt_parser <- optparse::OptionParser(option_list = option_list)
opt <- optparse::parse_args(opt_parser)


# Establish output folder
output_folder <- file.path(opt$output_dir)
if (!dir.exists(output_folder)) {
dir.create(output_folder, recursive = TRUE)
}

# Retrieve base_url for github pages if it has not been specified
if (is.null(opt$base_url)) {
base_url <- cow::get_pages_url(repo_name = opt$repo, git_pat = opt$git_pat)
base_url <- gsub("/$", "", base_url)
}


#### Get chapters
# Retrieve chapters from what's on the github pages
retrieve_chapters <- ottrpal::get_chapters(base_url)

## Get chapter list and urls
chapter_df <- data.frame(
retrieve_chapters,
full_urls = paste0(base_url, retrieve_chapters$url),
md_name = paste0(gsub(" ", "-", retrieve_chapters$chapt_title), ".md")
)

##### Get Quizzes
quiz_files <- list.files(file.path(root_dir, "quizzes"), pattern = ".md")

if (opt$make_book_txt) {
# Make book.txt fresh
ottrpal::bookdown_to_book_txt(md_files = list.files(file.path(root_dir, "manuscript"), pattern = ".md"))
}

## Read in Book.txt
book_txt <- readLines(file.path(root_dir, "manuscript", "Book.txt"))

## Make a data frame from this
book_txt_df <- data.frame(md_name = book_txt) %>%
dplyr::mutate(type = dplyr::case_when(
grepl("quiz", md_name) ~ "quiz",
TRUE ~ "chapter"))

# Join it to the chapter df
book_txt_df <- book_txt_df %>%
dplyr::left_join(chapter_df,
by = "md_name")

## Write this file.
### You may want to add due dates to this file manually.
readr::write_tsv(book_txt_df, file.path("resources", "course_units.tsv"))

206 changes: 206 additions & 0 deletions scripts/port_to_google_classroom.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
#!/usr/bin/env Rscript

# This script takes information about the curriculum that is set up into a dataframe by `make_material_df.R`
# and it ports all info to a Google Classroom using rgoogleclassroom

library(magrittr)
library(lubridate)


# Find .git root directory
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))

curriculum_df <- googlesheets4::read_sheet(
"https://docs.google.com/spreadsheets/d/14PRS2qEed3E636QsorJFkgN94ikj3SeF1AgpoC-0bo0/edit#gid=971038940",
sheet = "chapter_df"
)


### Figure out a rough schedule
total_units <- sum(curriculum_df$unit_time)

### 5 days a week * 15 weeks
number_of_days <- 5*15

units_per_day <- round(total_units/number_of_days)

### Set up rough schedule
start_date <- ymd("2023-07-03")
due_date_time <- hms("11:59:59")

dist_from_tues <- 3 - wday(start_date)
dist_from_thurs <- 5 - wday(start_date)

# We want due dates on the same
gaps <- seq(from = 0, to = 7*15, by = 7)

tuesdays <- start_date + dist_from_tues + days(gaps)
thursdays <- start_date + dist_from_thurs + days(gaps)

# Make a due_date column
curriculum_df <- curriculum_df %>%
dplyr::mutate(unit_period = cumsum(unit_time))

sum(curriculum_df$unit_time)/length(thursdays)

which(abs(x - your.number) == min(abs(x - your.number)))


###### Create a new course
devtools::load_all("../../Hutch/rgoogleclassroom")

authorize()
owner_id <- get_owner_id()
datatrail_course <- create_course(owner_id$id, name = "DataTrail")

#### Create topics
topic_ids <- lapply(unique(curriculum_df$topic), function(topic_name) {
topic_output <- create_topic(course_id = datatrail_course$id,
name = topic_name)
return(topic_output$topicId)
})

# Add topic_ids
curriculum_df <- curriculum_df %>% dplyr::inner_join(
data.frame(topic = unique(curriculum_df$topic), topic_id = unlist(topic_ids))
)


#### Create materials
material_prompt <- "Read this material at this link below before taking the next quiz."

chapter_df <- curriculum_df %>%
dplyr::filter(type == "Chapter") %>%
dplyr::select(topic_id, chapt_title, full_urls)

material_results <- purrr::pmap(chapter_df, function(topic_id, chapt_title, full_urls) {
create_material(course_id = datatrail_course$id,
topic_id = topic_id,
title = chapt_title,
link = full_urls,
description = material_prompt)
})

#### Create quizzes
quiz_assignment_prompt <- "Take the attached quiz! Remember to use the same email."
quiz_description_prompt <- "Answer the following questions after having read the chapters"

# Filter to only quizzes
quiz_df <- curriculum_df %>%
dplyr::filter(!is.na(quiz_file)) %>%
dplyr::select(quiz_file, topic_id, chapt_title)

# Convert quizzes to correct format
dir.create("quiz_jsons", showWarnings = FALSE)

convert_quizzes <- purrr::pmap(quiz_df[62:nrow(quiz_df), ], function(quiz_file, topic_id, chapt_title) {
ottr_quiz_to_google(course_id = datatrail_course$id,
quiz_path = file.path("quizzes", quiz_file),
form_id = "https://docs.google.com/forms/d/1eSCaKC7GDFsm60AKOWYHXK_yXCbrQbR-r2PomeKC_VY/edit",
topic_id = topic_id,
quiz_title = chapt_title,
new_name = chapt_title,
coursework_title = paste0("Quiz:", chapt_title),
due_date = "2025-5-1",
copy_from_template_quiz = TRUE,
quiz_description = quiz_description_prompt,
assignment_description = quiz_assignment_prompt,
output_path = file.path("quiz_jsons", gsub("\\.md$", ".json", quiz_file)))
})


### Set up Projects
# Put together the prompts
project_prompt <- readLines(file.path(root_dir, "scripts", "prompts", "project_prompt.md"))
project_prompt <- paste0(project_prompt, sep = "\n", collapse = "")

# Filter to only projects
project_df <- curriculum_df %>%
dplyr::filter(type == "Project") %>%
dplyr::select(topic_id, chapt_title)

# Set up data
folders_df <- data.frame(
folder_name =
c(
"01_Forming_Questions",
"02_Getting_Data",
"03_Cleaning_Data",
"04_Plotting_Data",
"05_Getting_Stats",
"06_Sharing_Results"
),
rmd_name = c(
"first_project.Rmd",
"leanpub_project.Rmd",
"countries_project.Rmd",
"airbnb_project.Rmd",
"countries_stats_project.Rmd",
"data_project_final.Rmd"
)
)

# Add the folder and Rmd names
project_df <- dplyr::bind_cols(project_df, folders_df)

create_projects <- purrr::pmap(project_df, function(topic_id, chapt_title, folder_name, rmd_name) {

# Fill in the blanks
project_description <- stringr::str_replace_all( project_prompt, "\\{FOLDER_NAME\\}", folder_name)
project_description <- stringr::str_replace_all(project_description, "\\{RMARKDOWN_NAME\\}", rmd_name)

result <- create_coursework(course_id = datatrail_course$id,
topic_id = topic_id,
title = paste("Project:", folder_name),
due_date = "2025-12-1",
description = project_description,
link = "https://posit.cloud/spaces/3919/content/4475631"
)
return(result)
})


#### Set up Swirl

# Put together the prompts
swirl_prompt <- readLines(file.path(root_dir, "scripts", "prompts", "swirl_prompt.md"))
swirl_prompt <- paste0(swirl_prompt, sep = "\n", collapse = "")

# Filter to only projects
swirl_df <- curriculum_df %>%
dplyr::filter(!is.na(module_name)) %>%
dplyr::select(topic_id, module_name, topic)

module_df <- data.frame(modules = c(
"DataTrail_01_Forming_Questions",
"DataTrail_02_Getting_Data",
"DataTrail_03_Cleaning_Data",
"DataTrail_04_Plotting_Data",
"DataTrail_05_Getting_Stats",
"DataTrail_06_Sharing_Results")) %>%
dplyr::mutate(topic = stringr::word(modules, sep = "_", start = -2, end = -1),
topic = gsub("_", " ", topic),
# I have to do this stupid thing because the topic is called 'Stats' and the module is called 'Statistics'
topic = gsub("Stats$", "Statistics", topic))

# Join the module names to the swirl_df
swirl_df <- dplyr::left_join(swirl_df, module_df, by = "topic") %>%
dplyr::select(-topic)


# Create the swirl assignments
create_swirls <- purrr::pmap(swirl_df, function(topic_id, module_name, modules) {

# Fill in the blanks
swirl_description <- stringr::str_replace_all(swirl_prompt, "\\{LESSON_NAME\\}", module_name)
swirl_description <- stringr::str_replace_all(swirl_description, "\\{COURSE_NAME\\}", modules)

result <- create_coursework(course_id = datatrail_course$id,
topic_id = topic_id,
title = paste("Swirl:", gsub("_", " ", module_name)),
due_date = "2025-12-1",
description = swirl_description,
link = "https://posit.cloud/spaces/3919/content/4475631"
)
return(result)
})
Loading