├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── export_app.R ├── list_apps.R ├── list_categories.R ├── list_keywords.R ├── markdown.R └── run_app.R ├── README.md ├── _pkgdown.yaml ├── appveyor.yml ├── docs ├── LICENSE-text.html ├── apple-touch-icon-120x120.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-76x76.png ├── apple-touch-icon.png ├── articles │ ├── index.html │ ├── z1_install.html │ ├── z2_usage.html │ └── z3_participate.html ├── authors.html ├── docsearch.css ├── docsearch.js ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── index.html ├── link.svg ├── logo.svg ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── export_app.html │ ├── figures │ │ └── logo.png │ ├── index.html │ ├── list_apps.html │ ├── list_categories.html │ ├── list_keywords.html │ └── run_app.html └── sitemap.xml ├── index.Rmd ├── inst ├── apps │ ├── aggregation_segregation │ │ ├── global.R │ │ ├── info │ │ ├── server.R │ │ ├── ui.R │ │ └── www │ │ │ ├── actions.js │ │ │ ├── custom.css │ │ │ └── white-rstudio-logo.png │ ├── ant_collective_decision │ │ ├── global.R │ │ ├── info │ │ ├── server.R │ │ ├── ui.R │ │ └── www │ │ │ ├── actions.js │ │ │ ├── custom.css │ │ │ └── white-rstudio-logo.png │ ├── axelrod │ │ ├── info │ │ └── www │ │ │ ├── actions.js │ │ │ ├── custom.css │ │ │ └── white-rstudio-logo.png │ ├── bee_house_hunting │ │ ├── global.R │ │ ├── info │ │ ├── server.R │ │ ├── ui.R │ │ └── www │ │ │ ├── actions.js │ │ │ ├── custom.css │ │ │ └── white-rstudio-logo.png │ ├── opinion_dynamics │ │ ├── global.R │ │ ├── info │ │ ├── server.R │ │ ├── ui.R │ │ └── www │ │ │ ├── actions.js │ │ │ ├── custom.css │ │ │ └── white-rstudio-logo.png │ └── wisdom_of_crowds │ │ ├── global.R │ │ ├── info │ │ ├── server.R │ │ ├── ui.R │ │ └── www │ │ ├── actions.js │ │ ├── custom.css │ │ └── white-rstudio-logo.png └── html_templates │ └── template.html ├── logo.png ├── logo.svg ├── man ├── export_app.Rd ├── figures │ └── logo.png ├── list_apps.Rd ├── list_categories.Rd ├── list_keywords.Rd └── run_app.Rd ├── pkgdown └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico ├── teachR.Rproj └── vignettes ├── z1_install.R ├── z1_install.Rmd ├── z1_install.html ├── z2_usage.Rmd ├── z2_usage.html ├── z3_participate.Rmd └── z3_participate.html /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | .travis.yml 4 | _pkgdown.yaml 5 | appveyor.yml 6 | index.Rmd 7 | logo.* 8 | LICENSE -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | src/*.o 5 | src/*.so 6 | src/*.dll 7 | .DS_STORE -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: R 2 | sudo: false 3 | cran: http://cran.rstudio.com 4 | cache: packages 5 | warnings_are_errors: false 6 | os: 7 | - linux 8 | - osx 9 | 10 | r_build_args: "--no-manual --no-build-vignettes" 11 | r_check_args: "--as-cran --ignore-vignettes --no-examples --install-args=--build" 12 | 13 | before_install: 14 | - fname=travis_helpers.sh 15 | - wget -O ${fname} http://bit.ly/travis_helpers 16 | - cat ${fname}; source ${fname}; rm ${fname} 17 | - cat DESCRIPTION 18 | - export PACKAGE_NAME=`package_name` 19 | - export RCHECK_DIR=${PACKAGE_NAME}.Rcheck 20 | 21 | after_success: 22 | - cat ${RCHECK_DIR}/00install.out 23 | - cat ${RCHECK_DIR}/00check.log 24 | 25 | after_failure: 26 | - cat ${RCHECK_DIR}/00install.out 27 | - cat ${RCHECK_DIR}/00check.log 28 | 29 | before_deploy: 30 | - if [ "$TRAVIS_OS_NAME" = "osx" ]; 31 | then 32 | PKG_TARBALL=$(ls -1t *.tgz | head -n 1); 33 | PKG_TARBALL_WITH_R=`echo $PKG_TARBALL | sed 's/.tgz/_'"R${rver}"'.tgz/'` ; 34 | mv ${PKG_TARBALL} ${PKG_TARBALL_WITH_R} ; 35 | echo "Built tarball is ${PKG_TARBALL_WITH_R}" ; 36 | fi 37 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; 38 | then 39 | PKG_TARBALL=$(ls -1t *.tar.gz | head -n 1); 40 | PKG_TARBALL_WITH_R=`echo $PKG_TARBALL | sed 's/.tar.gz/_'"R${rver}"'.tar.gz/'` ; 41 | mv ${PKG_TARBALL} ${PKG_TARBALL_WITH_R} ; 42 | echo "Built tarball is ${PKG_TARBALL_WITH_R}" ; 43 | fi 44 | - if [[ "${TRAVIS_OS_NAME}" = "osx" ]]; 45 | then 46 | rm -f *.tar.gz; 47 | fi 48 | 49 | deploy: 50 | provider: releases 51 | skip_cleanup: true 52 | api_key: 53 | secure: pVFJPm5rdLijONI/LaVsoaUH0jUJm2DfRROO2RoQanpRWGK+3r56ZcE/lgFGiCjmKigQhbDVY6ld/6Zt9ODI7pNFlu5fuSd4nGjY3RNjXO82kNCTHMHD79NGfHriHRzuAkjV/ahs7Vzotr3G9CMjwT1cgTqwJ4K03zoenZfZlRq4UzqLbaTaUn1z1UMZEFP1s4rP3/KTNwCbDxXkPSE6WDVtO+k4oCxKz5saLWkshrbcyBY409KLZgNpjIiHFWdUEFyUqMV9mFZkwH3duIbNQlFLK1IietHgmed4In1jr5JuyMH53aqDyE7zwxZPVR+Ct/3Zs6hRgVZrPHl9edMX+UdUXz5RES5efGOM/uvOle3F3tTMLj3f2iR7QlJ8KA/LXI97mmpJo47OT/2KhJHZNw6tmHDMhcAhnT3HPGgZkUMKToMqUGL3DUcuZO0IZ4I34BkBuuxVWO5GNcOEi/HwAKpD/d1Pww7eMlPzr5lnqpjZYMcqp+dtiNT6TFnM39gLVViIDTTSmr7uosNq6n0XAt3JhS/MkoQHSxz1bAaDXNu8ZVsQsW1EiujfWDz6gYd553RpCClaVYxNUC2bqXVtLuZMcT1afjx8Z5alPMJArXZELhv/TfjvwHB4hivj/6zlmS1SknNgoLwfQD66SC9j5b76r/VhTGHKDMkDDaGPMLw= 54 | file_glob: true 55 | file: ${PACKAGE_NAME}*.t*gz 56 | on: 57 | repo: swarm-lab/${PACKAGE_NAME} 58 | tags: true 59 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: teachR 2 | Type: Package 3 | Title: R Package For Distributing Web Applications For Educational Use 4 | Version: 0.2 5 | Authors@R: c( 6 | person("Simon", "Garnier", email = "garnier@njit.edu", role = c("aut", "cre"), 7 | comment = c(ORCID = "0000-0002-3886-3974")) 8 | ) 9 | Maintainer: Simon Garnier 10 | Description: teachR is a package for R that bundles several Shiny web 11 | applications for educational use. The goal of teachR is to provide teachers 12 | and educators with free, easy-to-use and interactive applications for 13 | complementing their courses with virtual demonstrations and/or experiments. 14 | License: GPL-3 15 | Imports: 16 | shiny (>= 1.2.0), 17 | pacman (>= 0.5.0), 18 | shinythemes (>= 1.1.2), 19 | dplyr (>= 0.7.8), 20 | markdown (>= 0.9), 21 | mime (>= 0.6) 22 | Suggests: 23 | knitr 24 | VignetteBuilder: knitr 25 | URL: https://swarm-lab.github.io/teachR/, https://github.com/swarm-lab/teachR 26 | BugReports: https://github.com/swarm-lab/teachR/issues 27 | RoxygenNote: 6.1.1 28 | Encoding: UTF-8 29 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(export_app) 4 | export(list_apps) 5 | export(list_categories) 6 | export(list_keywords) 7 | export(run_app) 8 | -------------------------------------------------------------------------------- /R/export_app.R: -------------------------------------------------------------------------------- 1 | #' @title Export \code{teachR} Apps 2 | #' 3 | #' @description This function exports a Shiny app provided by the 4 | #' \code{teachR} library to a local folder on 5 | #' a user's computer. Useful for modifying the app or running it on a Shiny 6 | #' Server instance for example. 7 | #' 8 | #' @param app The name of the app to export. 9 | #' 10 | #' @param dest The destination of the app folder on the user's computer. A folder 11 | #' with the name of the app will be created at this location. 12 | #' 13 | #' @return This function does not return anything. 14 | #' 15 | #' @author Simon Garnier, \email{garnier@@njit.edu} 16 | #' 17 | #' @examples 18 | #' \dontrun{ 19 | #' # Export app to the current working directory 20 | #' export_app("aggregation_segregation", ".") 21 | #' } 22 | #' 23 | #' @export 24 | export_app <- function(app, dest) { 25 | app_path <- paste0(find.package("teachR"), "/apps/", app) 26 | file.copy(from = app_path, to = dest, recursive = TRUE) 27 | } 28 | 29 | -------------------------------------------------------------------------------- /R/list_apps.R: -------------------------------------------------------------------------------- 1 | #' @title List \code{teachR} Apps 2 | #' 3 | #' @description This function generates a webpage listing all the apps available 4 | #' through the \code{teachR} library. The list can be filtered by category 5 | #' (type \code{list_categories()} for a list of existing categories) and 6 | #' keywords (type \code{list_keywords()} for a list of existing keywords). 7 | #' 8 | #' @param categories A character string or a vector of character strings 9 | #' corresponding to existing app categories (case insensitive). 10 | #' 11 | #' @param keywords A character string or a vector of character strings 12 | #' corresponding to existing app keywords (case insensitive). 13 | #' 14 | #' @return This function opens an html file. 15 | #' 16 | #' @author Simon Garnier, \email{garnier@@njit.edu} 17 | #' 18 | #' @details If called from RStudio, the list will open in the internal RStudio 19 | #' viewer. If called from a terminal, it will open in your default internet 20 | #' browser. 21 | #' 22 | #' @examples 23 | #' \dontrun{ 24 | #' list_apps(categories = c("biology", "social science")) 25 | #' } 26 | #' 27 | #' @export 28 | list_apps <- function(categories=NULL, keywords=NULL) { 29 | apps <- dir(paste0(find.package("teachR"), "/apps")) 30 | info_table <- data.frame() 31 | 32 | for (i in 1:length(apps)) { 33 | info <- utils::read.table(paste0(find.package("teachR"), "/apps/", apps[i], "/info"), sep = ":") 34 | info <- t(as.matrix(info)[, 2]) 35 | info_table <- rbind(info_table, info) 36 | } 37 | info_table[] <- lapply(info_table, as.character) 38 | names(info_table) <- c("Title", "Version", "Date", "Author", 39 | "Maintainer", "Description", "Category", 40 | "Keywords", "License", "Depends", "Command" ) 41 | 42 | md <- .make_list(info_table, categories, keywords) 43 | 44 | tmp_file <- tempfile(pattern = "file", fileext = ".html") 45 | out <- knitr::knit(text = md) 46 | markdown::markdownToHTML(text = out, output = tmp_file, options = c("toc"), 47 | title = "Apps available in teachR", 48 | template = paste0(find.package("teachR"), "/html_templates/template.html")) 49 | 50 | viewer <- getOption("viewer") 51 | if (!is.null(viewer)) 52 | viewer(tmp_file) 53 | else 54 | utils::browseURL(tmp_file) 55 | } 56 | 57 | 58 | .index <- function(x, pattern) { 59 | pattern <- paste(tolower(pattern), collapse = "|") 60 | x <- tolower(x) 61 | grepl(pattern, x) 62 | } 63 | 64 | 65 | .make_list <- function(info_table, categories = NULL, keywords = NULL) { 66 | if (!is.null(categories)) { 67 | info_table <- dplyr::filter(info_table, .index(Category, categories)) 68 | } 69 | if (!is.null(keywords)) { 70 | info_table <- dplyr::filter(info_table, .index(Keywords, keywords)) 71 | } 72 | 73 | if (nrow(info_table) > 0) { 74 | categories <- sort(unique(unlist(strsplit(info_table$Category, ",")))) 75 | md <- c("---") 76 | 77 | for (i in 1:length(categories)) { 78 | category <- sub(" ", "", categories[i]) 79 | md <- c(md, paste0("### ", category)) 80 | 81 | tmp <- dplyr::filter(info_table, .index(Category, categories[i])) 82 | 83 | for (j in 1:nrow(tmp)) { 84 | md <- c(md, "") 85 | 86 | md <- c(md, "") 87 | md <- c(md, paste0("")) 88 | md <- c(md, "") 89 | 90 | md <- c(md, "") 91 | md <- c(md, "") 92 | md <- c(md, paste0("")) 93 | md <- c(md, "") 94 | 95 | md <- c(md, "") 96 | md <- c(md, "") 97 | md <- c(md, paste0("")) 98 | md <- c(md, "") 99 | 100 | md <- c(md, "") 101 | md <- c(md, "") 102 | md <- c(md, paste0("")) 103 | md <- c(md, "") 104 | 105 | md <- c(md, "") 106 | md <- c(md, "") 107 | md <- c(md, paste0("")) 108 | md <- c(md, "") 109 | 110 | md <- c(md, "") 111 | md <- c(md, "") 112 | md <- c(md, paste0("")) 113 | md <- c(md, "") 114 | 115 | md <- c(md, "
", sub(" ", "", tmp$Title[j]), "
Command: ", "run_app(\"", sub(" ", "", tmp$Command[j]), "\")
Description: ", sub(" ", "", tmp$Description[j]), "
Keywords: ", sub(" ", "", tmp$Keywords[j]), "
Depends on: ", sub(" ", "", tmp$Depends[j]), "
Author: ", sub(" ", "", tmp$Author[j]), "
") 116 | } 117 | } 118 | } else { 119 | stop(paste0("There is no app matching these categories and/or keywords.")) 120 | } 121 | 122 | md 123 | } 124 | 125 | 126 | # .markdownToHTML <- function(file, output = NULL, text = NULL, 127 | # options = getOption("markdown.HTML.options"), 128 | # extensions = getOption("markdown.extensions"), title = "", 129 | # stylesheet = getOption("markdown.HTML.stylesheet"), 130 | # header = getOption("markdown.HTML.header"), 131 | # template = getOption("markdown.HTML.template"), fragment.only = FALSE, 132 | # encoding = getOption("encoding")) { 133 | # if (fragment.only) 134 | # options <- c(options, "fragment_only") 135 | # ret <- markdown::renderMarkdown(file, output = NULL, text, renderer = "HTML", 136 | # renderer.options = options, extensions = extensions, 137 | # encoding = encoding) 138 | # ret <- enc2native(ret) 139 | # if ("base64_images" %in% options) { 140 | # filedir <- if (!missing(file) && is.character(file) && 141 | # file.exists(file)) { 142 | # dirname(file) 143 | # } 144 | # else "." 145 | # ret <- local({ 146 | # oldwd <- setwd(filedir) 147 | # on.exit(setwd(oldwd)) 148 | # .b64EncodeImages(ret) 149 | # }) 150 | # } 151 | # if (!"fragment_only" %in% options) { 152 | # if (is.null(template)) 153 | # template <- system.file("resources", "markdown.html", 154 | # package = "markdown") 155 | # html <- paste(readLines(template), collapse = "\n") 156 | # html <- sub("#!html_output#", ret, html, fixed = TRUE) 157 | # if (is.character(stylesheet)) { 158 | # html <- sub("#!markdown_css#", option2char(stylesheet), 159 | # html, fixed = TRUE) 160 | # } 161 | # else { 162 | # warning("stylesheet must either be valid CSS or a file containing CSS!") 163 | # } 164 | # html <- sub("#!header#", option2char(header), html, fixed = TRUE) 165 | # if (!is.character(title) || title == "") { 166 | # m <- regexpr("<[Hh][1-6].*?>(.*)", 167 | # html, perl = TRUE) 168 | # if (m > -1) { 169 | # title <- regmatches(html, m) 170 | # title <- sub("<[Hh][1-6].*?>", "", title) 171 | # title <- sub("", "", title) 172 | # } 173 | # else { 174 | # title <- "" 175 | # } 176 | # } 177 | # html <- gsub("#!title#", title, html, fixed = TRUE) 178 | # if ("mathjax" %in% options && .requiresMathJax(html)) { 179 | # mathjax <- .mathJax(embed = "mathjax_embed" %in% 180 | # options) 181 | # } 182 | # else mathjax <- "" 183 | # html <- sub("#!mathjax#", mathjax, html, fixed = TRUE) 184 | # if ("highlight_code" %in% options && .requiresHighlighting(html)) { 185 | # highlight <- paste(readLines(system.file("resources", 186 | # "r_highlight.html", package = "markdown")), collapse = "\n") 187 | # } 188 | # else highlight <- "" 189 | # html <- sub("#!r_highlight#", highlight, html, fixed = TRUE) 190 | # ret <- html 191 | # } 192 | # if (is.character(output)) { 193 | # ret2 <- iconv(ret, to = "UTF-8") 194 | # if (any(is.na(ret2))) { 195 | # warning("failed to convert output to UTF-8; wrong input encoding or locale?") 196 | # } 197 | # else ret <- ret2 198 | # writeLines(ret, output, useBytes = TRUE) 199 | # ret <- NULL 200 | # } 201 | # invisible(ret) 202 | # } 203 | -------------------------------------------------------------------------------- /R/list_categories.R: -------------------------------------------------------------------------------- 1 | #' @title List Categories of All \code{teachR} Apps 2 | #' 3 | #' @description This function generates a listing of all the categories of apps 4 | #' available through the \code{teachR} library. 5 | #' 6 | #' @return A vector of character strings, each of them corresponding to a different 7 | #' category. 8 | #' 9 | #' @author Simon Garnier, \email{garnier@@njit.edu} 10 | #' 11 | #' @examples 12 | #' \dontrun{ 13 | #' list_categories() 14 | #' } 15 | #' 16 | #' @export 17 | list_categories <- function() { 18 | apps <- dir(paste0(find.package("teachR"), "/apps")) 19 | info_table <- data.frame() 20 | 21 | for (i in 1:length(apps)) { 22 | info <- utils::read.table(paste0(find.package("teachR"), "/apps/", apps[i], "/info"), sep = ":") 23 | info <- t(as.matrix(info)[, 2]) 24 | info_table <- rbind(info_table, info) 25 | } 26 | info_table[] <- lapply(info_table, as.character) 27 | names(info_table) <- c("Title", "Version", "Date", "Author", 28 | "Maintainer", "Description", "Category", 29 | "Keywords", "License", "Depends", "Command" ) 30 | 31 | categories <- strsplit(info_table$Category, ",") 32 | categories <- sort(unique(unlist(categories))) 33 | sub(" ", "", categories) 34 | } 35 | -------------------------------------------------------------------------------- /R/list_keywords.R: -------------------------------------------------------------------------------- 1 | #' @title List Keywords of All \code{teachR} Apps 2 | #' 3 | #' @description This function generates a listing of all the keywords of apps 4 | #' available through the \code{teachR} library. 5 | #' 6 | #' @return A vector of character strings, each of them corresponding to a different 7 | #' keyword. 8 | #' 9 | #' @author Simon Garnier, \email{garnier@@njit.edu} 10 | #' 11 | #' @examples 12 | #' \dontrun{ 13 | #' list_keywords() 14 | #' } 15 | #' 16 | #' @export 17 | list_keywords <- function() { 18 | apps <- dir(paste0(find.package("teachR"), "/apps")) 19 | info_table <- data.frame() 20 | 21 | for (i in 1:length(apps)) { 22 | info <- utils::read.table(paste0(find.package("teachR"), "/apps/", apps[i], "/info"), sep = ":") 23 | info <- t(as.matrix(info)[, 2]) 24 | info_table <- rbind(info_table, info) 25 | } 26 | info_table[] <- lapply(info_table, as.character) 27 | names(info_table) <- c("Title", "Version", "Date", "Author", 28 | "Maintainer", "Description", "Category", 29 | "Keywords", "License", "Depends", "Command" ) 30 | 31 | keywords <- strsplit(info_table$Keywords, ",") 32 | keywords <- sort(unique(unlist(keywords))) 33 | sub(" ", "", keywords) 34 | } 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /R/markdown.R: -------------------------------------------------------------------------------- 1 | #' # Functions copied from the markdown package 2 | #' .mathJax <- local({ 3 | #' js <- NULL 4 | #' 5 | #' function(embed=FALSE, force=FALSE) { 6 | #' if (!embed) 7 | #' return(paste(readLines(system.file( 8 | #' 'resources', 'mathjax.html', package = 'markdown' 9 | #' )), collapse = '\n')) 10 | #' 11 | #' url <- 'https://cdn.bootcss.com/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML' 12 | #' 13 | #' # Insert or link to MathJax script? 14 | #' html <- c('', if (embed) { 15 | #' # Already in cache? 16 | #' if (force || is.null(js)) { 17 | #' js <<- readLines(url, warn = FALSE) 18 | #' } 19 | #' c('') 23 | #' 24 | #' paste(html, collapse = "\n") 25 | #' } 26 | #' }) 27 | #' 28 | #' 29 | #' .requiresMathJax <- function(html) { 30 | #' regs <- c("\\\\\\(([\\s\\S]+?)\\\\\\)", "\\\\\\[([\\s\\S]+?)\\\\\\]") 31 | #' for (i in regs) if (any(grepl(i, html, perl = TRUE))) 32 | #' return(TRUE) 33 | #' FALSE 34 | #' } 35 | #' 36 | #' .requiresHighlighting <- function(html) { 37 | #' any(grepl("

12 | 
13 | `teachR` is a package for [`R`](http://www.r-project.org) that bundles several 
14 | [`Shiny`](http://shiny.rstudio.com/) web applications for educational use. 
15 | 
16 | The goal of `teachR` is to provide teachers and educators with free, easy-to-use
17 | and interactive applications for complementing their courses with virtual 
18 | demonstrations and/or experiments. 
19 | 
20 | The [`Shiny`](http://shiny.rstudio.com/) applications in `teachR` can be launched 
21 | directly from within [`R`](http://www.r-project.org) or [`RStudio`](http://www.rstudio.com). 
22 | They can also be exported toward a local folder for later deployment 
23 | on [`shinyapp.io`](https://www.shinyapps.io/) or on a personal 
24 | [`Shiny Server`](http://www.rstudio.com/products/shiny/shiny-server/) instance. 
25 | 
26 | The `teachR` package is at a very early stage of development. It contains only a 
27 | few [`Shiny`](http://shiny.rstudio.com/) applications at the moment, but this 
28 | number is meant to grow with the help of [`Shiny`](http://shiny.rstudio.com/) 
29 | developers looking to make their educational web applications more easily 
30 | accessible. 
31 | 
32 | If you are a [`Shiny`](http://shiny.rstudio.com/) developer and want to 
33 | participate, just fork this repository, add your application(s) to the "inst/apps" 
34 | folder with a properly formatted "info" file (see other apps for examples), and 
35 | send me a pull request. 
36 | 
37 | ---
38 | 
39 | ## Quick start guides
40 | 
41 | 1. [Installing teachR](https://swarm-lab.github.io/teachR/articles/z1_install)
42 | 2. [Using teachR](https://swarm-lab.github.io/ROpenCVLite/articles/z2_usage.html)
43 | 3. [Adding new apps to teachR](https://swarm-lab.github.io/ROpenCVLite/articles/z3_participate.html)
44 | 
45 | ---
46 | 


--------------------------------------------------------------------------------
/_pkgdown.yaml:
--------------------------------------------------------------------------------
 1 | url: https://swarm-lab.github.io/teachR/
 2 | 
 3 | template:
 4 |   params:
 5 |     bootswatch: yeti
 6 | #    docsearch:
 7 | #      api_key: 3a2946bbe34c635ad2e2aae74a83374b
 8 | #      index_name: swarm-lab-swarm
 9 | 
10 | authors:
11 |   Simon Garnier:
12 |     href: http://www.theswarmlab.com
13 | 
14 | development:
15 |   mode: unreleased
16 | 


--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
 1 | # DO NOT CHANGE
 2 | init:
 3 |   ps: |
 4 |     $ErrorActionPreference = "Stop"
 5 |     Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
 6 |     Import-Module '..\appveyor-tool.ps1'
 7 | 
 8 | install:
 9 |   ps: Bootstrap
10 | 
11 | cache:
12 |   - C:\RLibrary
13 | 
14 | 
15 | # Adapt as necessary starting from here
16 | environment:
17 |   global:
18 |     WARNINGS_ARE_ERRORS: 0.0
19 |     USE_RTOOLS: yes
20 |     R_CHECK_INSTALL_ARGS: --install-args=--build
21 | 
22 |   matrix:
23 |   - R_VERSION: stable
24 |     RTOOLS_VERSION: 34
25 |     CRAN: http://cran.rstudio.com
26 | 
27 | build_script:
28 |   - travis-tool.sh install_deps
29 | 
30 | test_script:
31 |   - travis-tool.sh run_tests
32 | 
33 | on_failure:
34 |   - 7z a failure.zip *.Rcheck\*
35 |   - appveyor PushArtifact failure.zip
36 | 
37 | artifacts:
38 |   - path: '*.Rcheck\**\*.log'
39 |     name: Logs
40 |   - path: '*.Rcheck\**\*.out'
41 |     name: Logs
42 |   - path: '*.Rcheck\**\*.fail'
43 |     name: Logs
44 |   - path: '*.Rcheck\**\*.Rout'
45 |     name: Logs
46 |   - path: '\*_*.tar.gz'
47 |     name: Bits
48 |   - path: '\*_*.zip'
49 |     name: Bits
50 | 
51 | deploy:
52 |   provider: GitHub
53 |   description: Windows Binary
54 |   auth_token:
55 |     secure: h+8/Q2kGkLoaoZ8OEtsplJGXuPFhS/VQbtE66cMJj7J3PeDgNAROVkV7368h3s+b
56 |   draft: no
57 |   prerelease: no
58 |   on:
59 |     APPVEYOR_REPO_TAG: true
60 | 


--------------------------------------------------------------------------------
/docs/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon-120x120.png


--------------------------------------------------------------------------------
/docs/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon-152x152.png


--------------------------------------------------------------------------------
/docs/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon-180x180.png


--------------------------------------------------------------------------------
/docs/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon-60x60.png


--------------------------------------------------------------------------------
/docs/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon-76x76.png


--------------------------------------------------------------------------------
/docs/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/apple-touch-icon.png


--------------------------------------------------------------------------------
/docs/articles/index.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | 
  4 |   
  5 |   
  6 | 
  7 | 
  8 | 
  9 | Articles • teachR
 10 | 
 11 | 
 12 | 
 13 | 
 14 | 
 15 | 
 16 | 
 17 | 
 18 | 
 19 | 
 20 | 
 21 | 
 22 | 
 23 | 
 24 | 
 25 | 
 26 | 
 27 | 
 28 | 
 29 | 
 30 | 
 31 | 
 32 | 
 33 | 
 34 | 
 35 | 
 36 | 
 37 | 
 38 | 
 39 | 
 40 | 
 41 | 
 42 | 
 43 | 
 44 | 
 45 | 
 46 | 
 47 | 
 48 | 
 49 | 
 50 | 
 51 | 
 55 | 
 56 | 
 57 |   
 58 | 
 59 |   
 60 |     
61 |
62 | 120 | 121 | 122 |
123 | 124 |
125 |
126 | 129 | 130 |
131 |

All vignettes

132 |

133 | 134 | 139 |
140 |
141 |
142 | 143 |
144 | 147 | 148 |
149 |

Site built with pkgdown 1.3.0.

150 |
151 |
152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /docs/articles/z1_install.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 - Installing teachR • teachR 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 |
29 |
87 | 88 | 89 | 90 |
91 |
92 | 100 | 101 | 102 | 103 |

This page describes the installation process of teachR.

104 |

teachR has not been released on CRAN yet, but it can be easily installed from its GitHub repository with the following steps.

105 |
106 | 111 |
112 |
113 |

114 | 1.1 - Before installing

115 |

Before installing teachR, you will need to install the latest version of the devtools package. You can install devtools from CRAN as follows:

116 |
if (!require(devtools))
117 |   install.packages("devtools")
118 |
119 |
120 |
121 |

122 | 1.2 - Installing teachR

123 |

You can install teachR as follows:

124 |
devtools::install_github("swarm-lab/teachR")
125 |
126 |
127 |
128 |

129 | 1.3 - Loading teachR

130 |
library(teachR)
131 |
132 |
133 | 134 | 145 | 146 |
147 | 148 | 149 |
152 | 153 |
154 |

Site built with pkgdown 1.3.0.

155 |
156 |
157 |
158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/articles/z2_usage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 - Installing teachR • teachR 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 |
29 |
87 | 88 | 89 | 90 |
91 |
92 | 100 | 101 | 102 | 103 |

This page describes how to use teachR.

104 |
105 | 106 | 108 | 109 |
110 | 111 | 112 |
115 | 116 |
117 |

Site built with pkgdown 1.3.0.

118 |
119 |
120 |
121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/articles/z3_participate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 - Installing teachR • teachR 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 |
29 |
87 | 88 | 89 | 90 |
91 |
92 | 100 | 101 | 102 | 103 |

This page describes how to add apps to teachR.

104 |
105 | 106 | 108 | 109 |
110 | 111 | 112 |
115 | 116 |
117 |

Site built with pkgdown 1.3.0.

118 |
119 |
120 |
121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 |
61 |
62 | 120 | 121 | 122 |
123 | 124 |
125 |
126 | 129 | 130 |
    131 |
  • 132 |

    Simon Garnier. Author, maintainer. ORCID 133 |

    134 |
  • 135 |
136 | 137 |
138 | 139 |
140 | 141 | 142 |
143 | 146 | 147 |
148 |

Site built with pkgdown 1.3.0.

149 |
150 |
151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/favicon.ico -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 13 | teachR 14 | 15 | 16 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body > .container { 21 | display: flex; 22 | height: 100%; 23 | flex-direction: column; 24 | 25 | padding-top: 60px; 26 | } 27 | 28 | body > .container .row { 29 | flex: 1 0 auto; 30 | } 31 | 32 | footer { 33 | margin-top: 45px; 34 | padding: 35px 0 36px; 35 | border-top: 1px solid #e5e5e5; 36 | color: #666; 37 | display: flex; 38 | flex-shrink: 0; 39 | } 40 | footer p { 41 | margin-bottom: 0; 42 | } 43 | footer div { 44 | flex: 1; 45 | } 46 | footer .pkgdown { 47 | text-align: right; 48 | } 49 | footer p { 50 | margin-bottom: 0; 51 | } 52 | 53 | img.icon { 54 | float: right; 55 | } 56 | 57 | img { 58 | max-width: 100%; 59 | } 60 | 61 | /* Fix bug in bootstrap (only seen in firefox) */ 62 | summary { 63 | display: list-item; 64 | } 65 | 66 | /* Typographic tweaking ---------------------------------*/ 67 | 68 | .contents .page-header { 69 | margin-top: calc(-60px + 1em); 70 | } 71 | 72 | /* Section anchors ---------------------------------*/ 73 | 74 | a.anchor { 75 | margin-left: -30px; 76 | display:inline-block; 77 | width: 30px; 78 | height: 30px; 79 | visibility: hidden; 80 | 81 | background-image: url(./link.svg); 82 | background-repeat: no-repeat; 83 | background-size: 20px 20px; 84 | background-position: center center; 85 | } 86 | 87 | .hasAnchor:hover a.anchor { 88 | visibility: visible; 89 | } 90 | 91 | @media (max-width: 767px) { 92 | .hasAnchor:hover a.anchor { 93 | visibility: hidden; 94 | } 95 | } 96 | 97 | 98 | /* Fixes for fixed navbar --------------------------*/ 99 | 100 | .contents h1, .contents h2, .contents h3, .contents h4 { 101 | padding-top: 60px; 102 | margin-top: -40px; 103 | } 104 | 105 | /* Static header placement on mobile devices */ 106 | @media (max-width: 767px) { 107 | .navbar-fixed-top { 108 | position: absolute; 109 | } 110 | .navbar { 111 | padding: 0; 112 | } 113 | } 114 | 115 | 116 | /* Sidebar --------------------------*/ 117 | 118 | #sidebar { 119 | margin-top: 30px; 120 | } 121 | #sidebar h2 { 122 | font-size: 1.5em; 123 | margin-top: 1em; 124 | } 125 | 126 | #sidebar h2:first-child { 127 | margin-top: 0; 128 | } 129 | 130 | #sidebar .list-unstyled li { 131 | margin-bottom: 0.5em; 132 | } 133 | 134 | .orcid { 135 | height: 16px; 136 | vertical-align: middle; 137 | } 138 | 139 | /* Reference index & topics ----------------------------------------------- */ 140 | 141 | .ref-index th {font-weight: normal;} 142 | 143 | .ref-index td {vertical-align: top;} 144 | .ref-index .icon {width: 40px;} 145 | .ref-index .alias {width: 40%;} 146 | .ref-index-icons .alias {width: calc(40% - 40px);} 147 | .ref-index .title {width: 60%;} 148 | 149 | .ref-arguments th {text-align: right; padding-right: 10px;} 150 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 151 | .ref-arguments .name {width: 20%;} 152 | .ref-arguments .desc {width: 80%;} 153 | 154 | /* Nice scrolling for wide elements --------------------------------------- */ 155 | 156 | table { 157 | display: block; 158 | overflow: auto; 159 | } 160 | 161 | /* Syntax highlighting ---------------------------------------------------- */ 162 | 163 | pre { 164 | word-wrap: normal; 165 | word-break: normal; 166 | border: 1px solid #eee; 167 | } 168 | 169 | pre, code { 170 | background-color: #f8f8f8; 171 | color: #333; 172 | } 173 | 174 | pre code { 175 | overflow: auto; 176 | word-wrap: normal; 177 | white-space: pre; 178 | } 179 | 180 | pre .img { 181 | margin: 5px 0; 182 | } 183 | 184 | pre .img img { 185 | background-color: #fff; 186 | display: block; 187 | height: auto; 188 | } 189 | 190 | code a, pre a { 191 | color: #375f84; 192 | } 193 | 194 | a.sourceLine:hover { 195 | text-decoration: none; 196 | } 197 | 198 | .fl {color: #1514b5;} 199 | .fu {color: #000000;} /* function */ 200 | .ch,.st {color: #036a07;} /* string */ 201 | .kw {color: #264D66;} /* keyword */ 202 | .co {color: #888888;} /* comment */ 203 | 204 | .message { color: black; font-weight: bolder;} 205 | .error { color: orange; font-weight: bolder;} 206 | .warning { color: #6A0366; font-weight: bolder;} 207 | 208 | /* Clipboard --------------------------*/ 209 | 210 | .hasCopyButton { 211 | position: relative; 212 | } 213 | 214 | .btn-copy-ex { 215 | position: absolute; 216 | right: 0; 217 | top: 0; 218 | visibility: hidden; 219 | } 220 | 221 | .hasCopyButton:hover button.btn-copy-ex { 222 | visibility: visible; 223 | } 224 | 225 | /* mark.js ----------------------------*/ 226 | 227 | mark { 228 | background-color: rgba(255, 255, 51, 0.5); 229 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 230 | padding: 1px; 231 | } 232 | 233 | /* vertical spacing after htmlwidgets */ 234 | .html-widget { 235 | margin-bottom: 10px; 236 | } 237 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $("#sidebar") 6 | .stick_in_parent({offset_top: 40}) 7 | .on('sticky_kit:bottom', function(e) { 8 | $(this).parent().css('position', 'static'); 9 | }) 10 | .on('sticky_kit:unbottom', function(e) { 11 | $(this).parent().css('position', 'relative'); 12 | }); 13 | 14 | $('body').scrollspy({ 15 | target: '#sidebar', 16 | offset: 60 17 | }); 18 | 19 | $('[data-toggle="tooltip"]').tooltip(); 20 | 21 | var cur_path = paths(location.pathname); 22 | var links = $("#navbar ul li a"); 23 | var max_length = -1; 24 | var pos = -1; 25 | for (var i = 0; i < links.length; i++) { 26 | if (links[i].getAttribute("href") === "#") 27 | continue; 28 | // Ignore external links 29 | if (links[i].host !== location.host) 30 | continue; 31 | 32 | var nav_path = paths(links[i].pathname); 33 | 34 | var length = prefix_length(nav_path, cur_path); 35 | if (length > max_length) { 36 | max_length = length; 37 | pos = i; 38 | } 39 | } 40 | 41 | // Add class to parent
  • , and enclosing
  • if in dropdown 42 | if (pos >= 0) { 43 | var menu_anchor = $(links[pos]); 44 | menu_anchor.parent().addClass("active"); 45 | menu_anchor.closest("li.dropdown").addClass("active"); 46 | } 47 | }); 48 | 49 | function paths(pathname) { 50 | var pieces = pathname.split("/"); 51 | pieces.shift(); // always starts with / 52 | 53 | var end = pieces[pieces.length - 1]; 54 | if (end === "index.html" || end === "") 55 | pieces.pop(); 56 | return(pieces); 57 | } 58 | 59 | // Returns -1 if not found 60 | function prefix_length(needle, haystack) { 61 | if (needle.length > haystack.length) 62 | return(-1); 63 | 64 | // Special case for length-0 haystack, since for loop won't run 65 | if (haystack.length === 0) { 66 | return(needle.length === 0 ? 0 : -1); 67 | } 68 | 69 | for (var i = 0; i < haystack.length; i++) { 70 | if (needle[i] != haystack[i]) 71 | return(i); 72 | } 73 | 74 | return(haystack.length); 75 | } 76 | 77 | /* Clipboard --------------------------*/ 78 | 79 | function changeTooltipMessage(element, msg) { 80 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 81 | element.setAttribute('data-original-title', msg); 82 | $(element).tooltip('show'); 83 | element.setAttribute('data-original-title', tooltipOriginalTitle); 84 | } 85 | 86 | if(ClipboardJS.isSupported()) { 87 | $(document).ready(function() { 88 | var copyButton = ""; 89 | 90 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 91 | 92 | // Insert copy buttons: 93 | $(copyButton).prependTo(".hasCopyButton"); 94 | 95 | // Initialize tooltips: 96 | $('.btn-copy-ex').tooltip({container: 'body'}); 97 | 98 | // Initialize clipboard: 99 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 100 | text: function(trigger) { 101 | return trigger.parentNode.textContent; 102 | } 103 | }); 104 | 105 | clipboardBtnCopies.on('success', function(e) { 106 | changeTooltipMessage(e.trigger, 'Copied!'); 107 | e.clearSelection(); 108 | }); 109 | 110 | clipboardBtnCopies.on('error', function() { 111 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 112 | }); 113 | }); 114 | } 115 | })(window.jQuery || window.$) 116 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 1.19.2.1 2 | pkgdown: 1.3.0 3 | pkgdown_sha: ~ 4 | articles: 5 | z1_install: z1_install.html 6 | z2_usage: z2_usage.html 7 | z3_participate: z3_participate.html 8 | urls: 9 | reference: https://swarm-lab.github.io/teachR//reference 10 | article: https://swarm-lab.github.io/teachR//articles 11 | 12 | -------------------------------------------------------------------------------- /docs/reference/export_app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Export <code>teachR</code> Apps — export_app • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 125 | 126 | 127 |
    128 | 129 |
    130 |
    131 | 136 | 137 |
    138 | 139 |

    This function exports a Shiny app provided by the 140 | teachR library to a local folder on 141 | a user's computer. Useful for modifying the app or running it on a Shiny 142 | Server instance for example.

    143 | 144 |
    145 | 146 |
    export_app(app, dest)
    147 | 148 |

    Arguments

    149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 159 | 160 |
    app

    The name of the app to export.

    dest

    The destination of the app folder on the user's computer. A folder 158 | with the name of the app will be created at this location.

    161 | 162 |

    Value

    163 | 164 |

    This function does not return anything.

    165 | 166 | 167 |

    Examples

    168 |
    # NOT RUN {
    169 |  # Export app to the current working directory
    170 |  export_app("aggregation_segregation", ".")
    171 | # }
    172 |
    173 |
    174 | 187 |
    188 | 189 |
    190 | 193 | 194 |
    195 |

    Site built with pkgdown 1.3.0.

    196 |
    197 |
    198 |
    199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/reference/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/docs/reference/figures/logo.png -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 |
    61 |
    62 | 120 | 121 | 122 |
    123 | 124 |
    125 |
    126 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 144 | 145 | 146 | 147 | 150 | 151 | 152 | 153 | 156 | 157 | 158 | 159 | 162 | 163 | 164 | 165 | 168 | 169 | 170 | 171 | 174 | 175 | 176 | 177 |
    141 |

    All functions

    142 |

    143 |
    148 |

    export_app()

    149 |

    Export teachR Apps

    154 |

    list_apps()

    155 |

    List teachR Apps

    160 |

    list_categories()

    161 |

    List Categories of All teachR Apps

    166 |

    list_keywords()

    167 |

    List Keywords of All teachR Apps

    172 |

    run_app()

    173 |

    Run teachR Apps

    178 |
    179 | 180 | 186 |
    187 | 188 |
    189 | 192 | 193 |
    194 |

    Site built with pkgdown 1.3.0.

    195 |
    196 |
    197 |
    198 | 199 | 200 | 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /docs/reference/list_apps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | List <code>teachR</code> Apps — list_apps • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 125 | 126 | 127 |
    128 | 129 |
    130 |
    131 | 136 | 137 |
    138 | 139 |

    This function generates a webpage listing all the apps available 140 | through the teachR library. The list can be filtered by category 141 | (type list_categories() for a list of existing categories) and 142 | keywords (type list_keywords() for a list of existing keywords).

    143 | 144 |
    145 | 146 |
    list_apps(categories = NULL, keywords = NULL)
    147 | 148 |

    Arguments

    149 | 150 | 151 | 152 | 153 | 155 | 156 | 157 | 158 | 160 | 161 |
    categories

    A character string or a vector of character strings 154 | corresponding to existing app categories (case insensitive).

    keywords

    A character string or a vector of character strings 159 | corresponding to existing app keywords (case insensitive).

    162 | 163 |

    Value

    164 | 165 |

    This function opens an html file.

    166 | 167 |

    Details

    168 | 169 |

    If called from RStudio, the list will open in the internal RStudio 170 | viewer. If called from a terminal, it will open in your default internet 171 | browser.

    172 | 173 | 174 |

    Examples

    175 |
    # NOT RUN {
    176 |  list_apps(categories = c("biology", "social science"))
    177 | # }
    178 |
    179 |
    180 | 195 |
    196 | 197 |
    198 | 201 | 202 |
    203 |

    Site built with pkgdown 1.3.0.

    204 |
    205 |
    206 |
    207 | 208 | 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /docs/reference/list_categories.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | List Categories of All <code>teachR</code> Apps — list_categories • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 123 | 124 | 125 |
    126 | 127 |
    128 |
    129 | 134 | 135 |
    136 | 137 |

    This function generates a listing of all the categories of apps 138 | available through the teachR library.

    139 | 140 |
    141 | 142 |
    list_categories()
    143 | 144 |

    Value

    145 | 146 |

    A vector of character strings, each of them corresponding to a different 147 | category.

    148 | 149 | 150 |

    Examples

    151 |
    # NOT RUN {
    152 |  list_categories()
    153 | # }
    154 |
    155 |
    156 | 168 |
    169 | 170 |
    171 | 174 | 175 |
    176 |

    Site built with pkgdown 1.3.0.

    177 |
    178 |
    179 |
    180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /docs/reference/list_keywords.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | List Keywords of All <code>teachR</code> Apps — list_keywords • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 123 | 124 | 125 |
    126 | 127 |
    128 |
    129 | 134 | 135 |
    136 | 137 |

    This function generates a listing of all the keywords of apps 138 | available through the teachR library.

    139 | 140 |
    141 | 142 |
    list_keywords()
    143 | 144 |

    Value

    145 | 146 |

    A vector of character strings, each of them corresponding to a different 147 | keyword.

    148 | 149 | 150 |

    Examples

    151 |
    # NOT RUN {
    152 |  list_keywords()
    153 | # }
    154 |
    155 |
    156 | 168 |
    169 | 170 |
    171 | 174 | 175 |
    176 |

    Site built with pkgdown 1.3.0.

    177 |
    178 |
    179 |
    180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /docs/reference/run_app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Run <code>teachR</code> Apps — run_app • teachR 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 61 | 62 | 63 | 64 |
    65 |
    66 | 124 | 125 | 126 |
    127 | 128 |
    129 |
    130 | 135 | 136 |
    137 | 138 |

    This function calls a Shiny app provided by the 139 | teachR library. The list of available Shiny apps can be obtained by 140 | typing list_apps() in your R terminal.

    141 | 142 |
    143 | 144 |
    run_app(app)
    145 | 146 |

    Arguments

    147 | 148 | 149 | 150 | 151 | 152 | 153 |
    app

    The name of the app to run.

    154 | 155 |

    Value

    156 | 157 |

    This function does not return anything.

    158 | 159 |

    Details

    160 | 161 |

    If called from RStudio, the app will open in the internal RStudio 162 | internet browser. If called from a terminal, it will open in your default 163 | internet browser. All apps should work without any problem with the internal 164 | RStudio internet browser, as well as with recent versions of most internet 165 | browsers. It is likely to break with older versions.

    166 | 167 | 168 |

    Examples

    169 |
    # NOT RUN {
    170 |  run_app("aggregation_segregation")
    171 | # }
    172 |
    173 |
    174 | 189 |
    190 | 191 |
    192 | 195 | 196 |
    197 |

    Site built with pkgdown 1.3.0.

    198 |
    199 |
    200 |
    201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://swarm-lab.github.io/teachR//index.html 5 | 6 | 7 | https://swarm-lab.github.io/teachR//reference/export_app.html 8 | 9 | 10 | https://swarm-lab.github.io/teachR//reference/list_apps.html 11 | 12 | 13 | https://swarm-lab.github.io/teachR//reference/list_categories.html 14 | 15 | 16 | https://swarm-lab.github.io/teachR//reference/list_keywords.html 17 | 18 | 19 | https://swarm-lab.github.io/teachR//reference/run_app.html 20 | 21 | 22 | https://swarm-lab.github.io/teachR//articles/z1_install.html 23 | 24 | 25 | https://swarm-lab.github.io/teachR//articles/z2_usage.html 26 | 27 | 28 | https://swarm-lab.github.io/teachR//articles/z3_participate.html 29 | 30 | 31 | -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | # teachR - R package for distributing web applications for educational use 6 | 7 | [![Travis-CI Build Status](https://travis-ci.org/swarm-lab/teachR.svg?branch=master)](https://travis-ci.org/swarm-lab/teachR) 8 | [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/swarm-lab/teachR?branch=master&svg=true)](https://ci.appveyor.com/project/swarm-lab/teachR) 9 | 10 | **Please submit all suggestions and bug reports 11 | [here](https://github.com/swarm-lab/teachR/issues). Thanks!** 12 | 13 | --- 14 | 15 | ## Description 16 | 17 | `teachR` is a package for [`R`](http://www.r-project.org) that bundles several 18 | [`Shiny`](http://shiny.rstudio.com/) web applications for educational use. 19 | 20 | The goal of `teachR` is to provide teachers and educators with free, easy-to-use 21 | and interactive applications for complementing their courses with virtual 22 | demonstrations and/or experiments. 23 | 24 | The [`Shiny`](http://shiny.rstudio.com/) applications in `teachR` can be launched 25 | directly from within [`R`](http://www.r-project.org) or [`RStudio`](http://www.rstudio.com). 26 | They can also be exported toward a local folder for later deployment 27 | on [`shinyapp.io`](https://www.shinyapps.io/) or on a personal 28 | [`Shiny Server`](http://www.rstudio.com/products/shiny/shiny-server/) instance. 29 | 30 | The `teachR` package is at a very early stage of development. It contains only a 31 | few [`Shiny`](http://shiny.rstudio.com/) applications at the moment, but this 32 | number is meant to grow with the help of [`Shiny`](http://shiny.rstudio.com/) 33 | developers looking to make their educational web applications more easily 34 | accessible. 35 | 36 | If you are a [`Shiny`](http://shiny.rstudio.com/) developer and want to 37 | participate, just fork this repository, add your application(s) to the "inst/apps" 38 | folder with a properly formatted "info" file (see other apps for examples), and 39 | send me a pull request. 40 | 41 | --- 42 | 43 | ## Quick start guides 44 | 45 | 1. [Installing teachR](https://swarm-lab.github.io/teachR/articles/z1_install) 46 | 2. [Using teachR](https://swarm-lab.github.io/ROpenCVLite/articles/z2_usage.html) 47 | 3. [Adding new apps to teachR](https://swarm-lab.github.io/ROpenCVLite/articles/z3_participate.html) 48 | 49 | --- 50 | -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/global.R: -------------------------------------------------------------------------------- 1 | #### LOAD LIBRARIES #### 2 | pacman::p_load(shiny, shinythemes, dplyr, ggvis) 3 | 4 | 5 | #### DEFINE CUSTOM FUNCTIONS #### 6 | #' @title Random Walk 7 | #' 8 | #' @description This function computes the next step of a random walk. 9 | #' 10 | #' @param df A data frame containing at least the following columns: x (x 11 | #' coordinates of each individual), y (y coordinates of each individual), h 12 | #' (heading in radians of each individual), s (the speed of each individual). 13 | #' 14 | #' @return A data frame of the same dimensions as \code{df}. 15 | #' 16 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 17 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 18 | #' 19 | rw <- function(df) { 20 | n <- nrow(df) 21 | 22 | within(df, { 23 | h <- h + rnorm(n, sd = pi / 6) 24 | x <- x + s * cos(h) 25 | y <- y + s * sin(h) 26 | 27 | h[x < -1] <- 0 28 | h[x > 1] <- pi 29 | h[y < -1] <- pi / 2 30 | h[y > 1] <- -pi / 2 31 | }) 32 | } 33 | 34 | 35 | #' @title Sigmoid Curve 36 | #' 37 | #' @description This function computes a fully customizable sigmoid function. 38 | #' 39 | #' @param x The x coordinates at which to compute the sigmoid values. 40 | #' @param a The sigmoid minimum value. 41 | #' @param k The sigmoid maximum value. 42 | #' @param b The growth rate of the sigmoid. 43 | #' @param m The position of the inflection point of the sigmoid. 44 | #' 45 | #' @return A vector of the same length as \code{x}. 46 | #' 47 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 48 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 49 | #' 50 | sigmoid <- function(x, a = 0, k = 1, b = 0.1, m = 100) { 51 | a + (k - a) / ((1 + exp(-b * (x - m)))) 52 | } 53 | 54 | 55 | #' @title Pairwise Distances 56 | #' 57 | #' @description This function computes the pairwise distances between two series 58 | #' of points. 59 | #' 60 | #' @param A A matrix for which the number of rows corresponds to the number of 61 | #' points and the number of colums corresponds to the number of dimensions in 62 | #' which these points are defined. 63 | #' @param B Same as \code{A}. In addition \code{B} must have the same number of 64 | #' columns as \code{A}. 65 | #' 66 | #' @return A matrix of the pairwise distances between the points in A (along the 67 | #' rows) and B (along the columns). 68 | #' 69 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 70 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 71 | #' 72 | pdist <- function(A, B) { 73 | if (ncol(A) != ncol(B)) { 74 | stop("A and B should have the same number of columns.") 75 | } 76 | 77 | an = apply(A, 1, function(rvec) crossprod(rvec,rvec)) 78 | bn = apply(B, 1, function(rvec) crossprod(rvec,rvec)) 79 | 80 | m = nrow(A) 81 | n = nrow(B) 82 | 83 | tmp = matrix(rep(an, n), nrow = m) 84 | tmp = tmp + matrix(rep(bn, m), nrow = m, byrow = TRUE) 85 | sqrt( tmp - 2 * tcrossprod(A,B) ) 86 | } 87 | 88 | 89 | #' @title Speed Adjustment 90 | #' 91 | #' @description This function adjusts the speed of individuals based on the 92 | #' local neighborhood. 93 | #' 94 | #' @param df A data frame containing at least the following columns: x (x 95 | #' coordinates of each individual), y (y coordinates of each individual), h 96 | #' (heading in radians of each individual), s (the speed of each individual). 97 | #' @param affinSame The degree of affinity of an individual for other 98 | #' individuals of the same class (-1: repulsion; 1: attraction). 99 | #' @param affinOther The degree of affinity of an individual for other 100 | #' individuals of a different class (-1: repulsion; 1: attraction). 101 | #' 102 | #' @return A data frame of the same dimensions as \code{df}. 103 | #' 104 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 105 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 106 | #' 107 | sp <- function(df, affinSame = 0, affinOther = 0) { 108 | dist <- pdist(as.matrix(df[, 1:2]), as.matrix(df[, 1:2])) 109 | neighbor <- dist < 0.125 110 | b_neighbor <- apply(df$col == "#107AB6" & neighbor, 2, sum) - (df$col == "#107AB6") 111 | r_neighbor <- apply(df$col == "#D86810" & neighbor, 2, sum) - (df$col == "#D86810") 112 | 113 | nb <- (df$col == "#107AB6") * affinSame * b_neighbor + 114 | (df$col == "#D86810") * affinSame * r_neighbor + 115 | (df$col == "#107AB6") * affinOther * r_neighbor + 116 | (df$col == "#D86810") * affinOther * b_neighbor 117 | 118 | df$s <- sigmoid(nb, k = 0.1, m = 4, b = -1) 119 | df 120 | } 121 | 122 | 123 | ### DEFINE GLOBAL VARIABLES ### 124 | pop <- NULL 125 | run <- FALSE 126 | -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/info: -------------------------------------------------------------------------------- 1 | Title: Self-organized aggregation and segregation 2 | Version: 0.1 3 | Date: 2015-05-13 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the principle of self-organized aggregation and segregation. 7 | Category: Biology, Social Science 8 | Keywords: Aggregation, Segregation, Self-Organization 9 | License: GPL (>= 3) 10 | Depends: dplyr (>= 0.4.1), ggvis (>= 0.4.3) 11 | Command: aggregation_segregation -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output, session) { 2 | 3 | react <- reactiveValues(count = 0) 4 | 5 | observe({ 6 | input$reset 7 | isolate({ 8 | pop <<- data.frame(x = runif(input$nIndiv, min = -1, max = 1), 9 | y = runif(input$nIndiv, min = -1, max = 1), 10 | h = runif(input$nIndiv, min = -pi, max = pi), 11 | s = 0.01, 12 | col = sample(c("#107AB6", "#D86810"), input$nIndiv, replace = TRUE)) 13 | }) 14 | react$count <- 0 15 | }) 16 | 17 | locs <- reactive({ 18 | invalidateLater(60, NULL) 19 | 20 | if (is.null(pop)) { 21 | return() 22 | } 23 | 24 | if (run) { 25 | isolate({ 26 | pop <<- sp(pop, input$affinSame, input$affinOther) 27 | pop <<- rw(pop) 28 | react$count <- react$count + 1 29 | }) 30 | } 31 | 32 | pop 33 | }) 34 | 35 | observe({ 36 | if (input$start > 0) { 37 | run <<- TRUE 38 | } 39 | }) 40 | 41 | observe({ 42 | if (input$stop > 0) { 43 | run <<- FALSE 44 | } 45 | }) 46 | 47 | output$count <- renderText({ 48 | react$count 49 | }) 50 | 51 | observe({ 52 | if (is.null(locs)) { 53 | return() 54 | } 55 | 56 | locs %>% 57 | ggvis(x = ~x, y = ~y) %>% 58 | layer_points(fill := ~col) %>% 59 | scale_numeric("x", domain = c(-1, 1)) %>% 60 | scale_numeric("y", domain = c(-1, 1)) %>% 61 | add_axis("x", title = "", properties = axis_props(labels = list(fontSize = 0))) %>% 62 | add_axis("x", title = "", properties = axis_props(labels = list(fontSize = 0)), orient = "top") %>% 63 | add_axis("y", title = "", properties = axis_props(labels = list(fontSize = 0))) %>% 64 | add_axis("y", title = "", properties = axis_props(labels = list(fontSize = 0)), orient = "right") %>% 65 | set_options(width = "auto", height = "100%", resizable = FALSE, 66 | duration = 30) %>% 67 | bind_shiny("display") 68 | }) 69 | }) 70 | 71 | -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI( 2 | navbarPage( 3 | title = "Aggregation, segregation", 4 | theme = shinytheme("cosmo"), 5 | fluid = FALSE, 6 | collapsible = TRUE, 7 | 8 | tabPanel("Model", 9 | 10 | includeCSS("www/custom.css"), 11 | 12 | # Sidebar 13 | sidebarLayout( 14 | sidebarPanel( 15 | width = 3, 16 | 17 | sliderInput("nIndiv", "Number of individuals", 18 | min = 2, max = 500, value = 200), 19 | 20 | tags$hr(), 21 | 22 | sliderInput("affinSame", "Affinity with same color", 23 | min = -1, max = 1, value = 0, step = 0.1), 24 | 25 | tags$hr(), 26 | 27 | sliderInput("affinOther", "Affinity with different color", 28 | min = -1, max = 1, value = 0, step = 0.1), 29 | 30 | tags$hr(), 31 | 32 | actionButton("start", "Start", style = "border: 2px solid; border-color: green; background-color: green;"), 33 | actionButton("stop", "Stop", style = "border: 2px solid; border-color: red; background-color: red;"), 34 | actionButton("reset", "Reset", style = "border: 2px solid; border-color: black;"), 35 | 36 | tags$hr(), 37 | 38 | tags$p("Step:", textOutput("count", inline = TRUE)), 39 | 40 | tags$hr() 41 | 42 | ), 43 | 44 | # Main panel 45 | mainPanel( 46 | fluidRow( 47 | ggvisOutput("display") 48 | ) 49 | ) 50 | ) 51 | ), 52 | 53 | tabPanel("Instructions", 54 | 55 | fluidRow( 56 | tags$hr(), 57 | 58 | h2("Goal"), 59 | 60 | p("This webapp simulates a simple aggregation mechanism."), 61 | 62 | p("In the absence of interaction, each individual particle moves 63 | randomly at maximum speed. When two particles move close to 64 | each other, they slow down if they have a positive affinity for 65 | each other, or accelerate if they have a negative affinity for 66 | each other. The amount of deceleration (resp. acceleration) 67 | depends on the strength of the affinity and the number of 68 | particles within the interaction range of each particle."), 69 | 70 | tags$hr(), 71 | 72 | h2("Parameters"), 73 | 74 | p("This simulation takes 3 parameters that you can modify using 75 | the sliders in the 'Model' tab."), 76 | 77 | tags$ol( 78 | tags$li(tags$b("Number of individuals: "), "this sets the number 79 | of particles in the simulation. Change this value to 80 | observe the effect of the particles' density on their 81 | aggregation behavior. The new value will not be taken 82 | into account unless you hit the 'Reset' button."), 83 | tags$li(tags$b("Affinity with same color: "), "this determines 84 | the level of affinity between particles of the same 85 | color. This parameter can be changed while the 86 | simulation is running."), 87 | tags$li(tags$b("Affinity with different color: "), "this determines 88 | the level of affinity between particles of different 89 | colors. This parameter can be changed while the 90 | simulation is running.") 91 | ), 92 | 93 | p("Use the 'Start' and 'Stop' buttons to run or pause the 94 | simulation. The 'Reset' button will disperse the particles 95 | randomly and update their number - if the corresponding 96 | parameter has been modified."), 97 | 98 | tags$hr(), 99 | 100 | h2("Outputs"), 101 | 102 | p("This simulation returns an animated graph representing the XY 103 | positions of the particles."), 104 | 105 | tags$hr() 106 | ) 107 | ), 108 | 109 | tabPanel("About", 110 | 111 | fluidRow( 112 | tags$hr(), 113 | 114 | p(strong("Author:"), " Simon Garnier (", a("New Jersey Institute of Technology", 115 | href = "http://www.njit.edu", 116 | target = "_blank"), ")"), 117 | 118 | p(strong("Twitter:"), a("@sjmgarnier", 119 | href = "https://twitter.com/sjmgarnier", 120 | target = "_blank")), 121 | 122 | p(strong("Website:"), a("http://www.theswarmlab.com", 123 | href = "http://www.theswarmlab.com", 124 | target = "_blank")), 125 | 126 | p(strong("Source code:"), 127 | a("GitHub", 128 | href = "https://github.com/swarm-lab/teachR/tree/master/inst/apps/aggregation_segregation", 129 | target = "_blank")), 130 | 131 | p(strong("Created with:"), 132 | a("RStudio", 133 | href = "http://www.rstudio.com/", 134 | target = "_blank"), 135 | " and ", 136 | a("Shiny.", 137 | href = "http://shiny.rstudio.com", 138 | target = "_blank")), 139 | 140 | p(strong("License:"), 141 | a("GPL v3", 142 | href = "http://www.gnu.org/copyleft/gpl.html", 143 | target = "_blank")), 144 | 145 | tags$hr() 146 | ) 147 | ), 148 | 149 | tabPanel(tagList(tags$html("Powered by"), 150 | tags$img(src = "white-rstudio-logo.png", 151 | height = "20")), 152 | value = "RStudio", 153 | tags$head(tags$script(src = "actions.js")) 154 | ) 155 | ) 156 | ) 157 | 158 | -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/www/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/aggregation_segregation/www/custom.css -------------------------------------------------------------------------------- /inst/apps/aggregation_segregation/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/aggregation_segregation/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/global.R: -------------------------------------------------------------------------------- 1 | #### LOAD LIBRARIES #### 2 | pacman::p_load(shiny, shinythemes, deSolve, dplyr, plotly) 3 | 4 | 5 | #### DEFINE CUSTOM FUNCTIONS #### 6 | #' @title ODE System 7 | #' 8 | #' @description This function represents the ODE system to simulate the 9 | #' collective selection of a food source by ant colonies. 10 | #' 11 | #' @param t The time step to compute the ODE at. 12 | #' @param y The values of the state variables of the ODE at the time step: 13 | #' number of ants at the nest (N) and at each food source (S1...Sn), quantity 14 | #' of pheromone on the routes to each food source (Q1...Qn). 15 | #' @param parms Parameters of the ODE system: 16 | #' \itemize{ 17 | #' \item l: Distance to each food source in seconds. 18 | #' \item q: Quantity of pheromone deposited by the ants on the way back from 19 | #' each food source. 20 | #' \item qe: Quantity of pheromone deposited by the ants on the way to the 21 | #' food sources. 22 | #' \item alpha, beta, gamma, eta: Regulates recruitment at the nest as a 23 | #' function of the quantity of pheromone at the nest entrance. 24 | #' \item psi: Probability for an ant to leave the food source. 25 | #' \item rho: Rate of evaporation of the pheromone. 26 | #' \item k: Intrinsic attractiveness of each route. 27 | #' \item n: Degree of nonlinearity. 28 | #' } 29 | #' 30 | #' @return A list of the changes in \code{y} suitable for \code{\link{dede}} 31 | #' function. 32 | #' 33 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 34 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 35 | #' 36 | ode_sys <- function(t, y, parms) { 37 | nS <- length(parms$l) 38 | 39 | Q <- sum(y[(nS + 2):(2 * nS + 1)]) 40 | phi <- (parms$alpha * (parms$beta + Q) ^ parms$eta) / ((parms$beta + Q) ^ parms$eta + parms$gamma) 41 | 42 | dN <- -phi*y[1] 43 | dS <- rep(0,nS) 44 | dQ <- rep(0,nS) 45 | 46 | ylag <- {} 47 | 48 | for (i in 1:nS) { 49 | if (t < parms$l[i]) { 50 | ylag <- c(parms$iniN, parms$iniS, parms$iniQ) 51 | Qlag <- 0 52 | philag <- 0 53 | } else { 54 | ylag <- lagvalue(t - parms$l[i]) 55 | Qlag <- sum(ylag[(nS + 2):(2 * nS + 1)]) 56 | philag <- (parms$alpha * (parms$beta + Qlag) ^ parms$eta) / ((parms$beta + Qlag) ^ parms$eta + parms$gamma) 57 | } 58 | 59 | P <- ((parms$k[i] + y[i + nS + 1]) ^ parms$n) / sum((parms$k + y[(nS + 2):(2 * nS + 1)]) ^ parms$n) 60 | Plag <- ((parms$k[i] + ylag[i + nS + 1]) ^ parms$n) / sum((parms$k + ylag[(nS + 2):(2 * nS + 1)]) ^ parms$n) 61 | 62 | dN <- dN + parms$psi*ylag[i + 1] 63 | 64 | dS[i] <- -parms$psi*y[i + 1] + philag * ylag[1] * Plag 65 | 66 | dQ[i] <- parms$qe * P * phi * y[1] + parms$q[i] * parms$psi * ylag[i + 1] - parms$rho * y[i + nS + 1] 67 | 68 | } 69 | 70 | return(list(c(dN, dS, dQ))) 71 | } 72 | -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/info: -------------------------------------------------------------------------------- 1 | Title: Collective food source selection in ants. 2 | Version: 0.1 3 | Date: 2015-05-13 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the principle of collective decision-making in ants. 7 | Category: Biology 8 | Keywords: Ants, Decision-making, Self-Organization 9 | License: GPL (>= 3) 10 | Depends: dplyr (>= 0.4.1), plotly (>= 4.5.6), deSolve (>= 1.11) 11 | Command: ant_collective_decision -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output) { 2 | 3 | res <- reactive({ 4 | parms <- list(iniN = input$N, 5 | iniS = rep(0,2), 6 | iniQ = rep(0,2), 7 | l = c(input$l1, input$l2), 8 | q = c(input$q1, input$q2), 9 | qe = 0, 10 | alpha = 0.01, 11 | beta = 5, 12 | gamma = 1200, 13 | eta = 2, 14 | psi = 0.05, 15 | rho = 0.01, 16 | k = c(100 - input$k1 + 1, 100 - input$k2 + 1), 17 | n = 2) 18 | 19 | out <- dede(c(N = parms$iniN, S = parms$iniS, Q = parms$iniQ), 20 | seq(0, 3600, length.out = 360), 21 | ode_sys, 22 | parms) 23 | 24 | data.frame(time = rep(out[, 1], 2), 25 | S = c(rep("Source 1", nrow(out)), rep("Source 2", nrow(out))), 26 | val = c(out[, 3], out[, 4])) 27 | }) 28 | 29 | output$the_display <- renderPlotly({ 30 | g <- ggplot(data = res(), aes(x = time, y = val, color = S)) + 31 | geom_path(size = 0.75) + 32 | theme_minimal(base_size = 16) + 33 | theme(legend.title = element_blank()) + 34 | xlab("Time") + ylab("Number of ants") + 35 | scale_color_manual(values = c("#2678B2", "#FD7F28")) 36 | 37 | ggplotly(g) %>% 38 | layout(legend = list(x = 0.5, y = 1.1, orientation = "h", xanchor = "center"), 39 | hovermode = "x") 40 | }) 41 | 42 | }) 43 | -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI( 2 | navbarPage( 3 | title = "Collective food source selection in ants", 4 | theme = shinytheme("cosmo"), 5 | fluid = FALSE, 6 | collapsible = TRUE, 7 | 8 | tabPanel("Model", 9 | 10 | includeCSS("www/custom.css"), 11 | 12 | # Sidebar 13 | sidebarLayout( 14 | sidebarPanel( 15 | width = 3, 16 | 17 | h4(tags$b("Source #1")), 18 | sliderInput('l1', 'Distance:', ticks = FALSE, 19 | min = 0, max = 100, value = 20, step = 1, width = "100%"), 20 | sliderInput('q1', 'Quality:', ticks = FALSE, 21 | min = 0, max = 2, value = 1, step = 0.01, width = "100%"), 22 | sliderInput('k1', 'Light intensity:', ticks = FALSE, 23 | min = 0, max = 100, value = 20, step = 1, width = "100%"), 24 | 25 | hr(), 26 | 27 | h4(tags$b("Source #2")), 28 | sliderInput('l2', 'Distance:', ticks = FALSE, 29 | min = 0, max = 100, value = 25, step = 1, width = "100%"), 30 | sliderInput('q2', 'Quality:', ticks = FALSE, 31 | min = 0, max = 2, value = 1, step = 0.01, width = "100%"), 32 | sliderInput('k2', 'Light intensity:', ticks = FALSE, 33 | min = 0, max = 100, value = 20, step = 1, width = "100%") 34 | ), 35 | 36 | # Main panel 37 | mainPanel( 38 | fluidRow( 39 | id = "the_display_row", 40 | column(12, plotlyOutput("the_display", height = "100%")) 41 | ), 42 | 43 | fluidRow( 44 | column(12, 45 | sliderInput('N', 'Number of ants in the colony:', 46 | min = 0, max = 5000, value = 1000, step = 10, width = "100%") 47 | ) 48 | ) 49 | ) 50 | ) 51 | ), 52 | 53 | tabPanel("Instructions", 54 | 55 | fluidRow( 56 | tags$hr(), 57 | 58 | h2("Goal"), 59 | 60 | p("This webapp simulates the collective decision-making mechanism 61 | of mass-recruiting ant colonies."), 62 | 63 | p("The underlying model is a system of differential equations 64 | directly inspired from the work of Jean-Louis Deneubourg and 65 | his collaborators during the 1980's and 1990's. Hereafter are a 66 | couple relevant publications regarding the equations that served 67 | as a basis for this simulation:"), 68 | 69 | tags$ol( 70 | tags$li( 71 | tags$a(href = "http://doi.org/10.1007/BF00462870", 72 | "Goss, S., Aron, S., Deneubourg, J. L., & Pasteels, 73 | J. M. (1989). Self-organized shortcuts in the Argentine 74 | ant. Die Naturwissenschaften, 76(12), 579–581.")), 75 | tags$li( 76 | tags$a(href = "http://doi.org/10.1007/BF02224053", 77 | "Beckers, R., Deneubourg, J.-L., Goss, S., & Pasteels, 78 | J. M. (1990). Collective decision making through food 79 | recruitment. Insectes Sociaux, 37(3), 258–267.")) 80 | ), 81 | 82 | tags$hr(), 83 | 84 | h2("Parameters"), 85 | 86 | p("This simulation takes 4 parameters that you can modify using 87 | the sliders in the 'Model' tab."), 88 | 89 | tags$ol( 90 | tags$li(tags$b("Number of ants in the colony: "), "this sets the 91 | total number of ants in the colony. Change this value to 92 | observe the effect of colony size on the speed and 93 | strength of the collective decision."), 94 | tags$li(tags$b("Distance: "), "this determines the distance in 95 | centimeters of the corresponding food source to the nest. 96 | The larger this value, the longer it will take ants to 97 | reach the food source and come back to the nest, and 98 | hence the longer it will take them to reinforce the 99 | pheromeone trail in between."), 100 | tags$li(tags$b("Quality: "), "this determines the sugar 101 | concentration in molar of the corresponding food source. 102 | Larger values indicates a more beneficial food source. 103 | Ants lay more pheromone on their trails when coming 104 | back from rich food sources than from poor ones."), 105 | tags$li(tags$b("Light intensity: "), "this determines how 106 | exposed to light is the path between the nest and a food 107 | source. Light is repellent for ants that prefer to walk 108 | along less exposed paths (most likely to reduce risks 109 | of predation or dessication). Higher values of this 110 | parameter indicate a more exposed path, and therefore a 111 | less attractive path.") 112 | ), 113 | 114 | tags$hr(), 115 | 116 | h2("Outputs"), 117 | 118 | p("This simulation returns a graph representing the number of ants 119 | at each food source (blue: source 1; orange: source 2) as a 120 | function of time (total time: 1 hour)."), 121 | 122 | tags$hr() 123 | ) 124 | ), 125 | 126 | tabPanel("About", 127 | 128 | fluidRow( 129 | tags$hr(), 130 | 131 | p(strong("Author:"), " Simon Garnier (", a("New Jersey Institute of Technology", 132 | href = "http://www.njit.edu", 133 | target = "_blank"), ")"), 134 | 135 | p(strong("Twitter:"), a("@sjmgarnier", 136 | href = "https://twitter.com/sjmgarnier", 137 | target = "_blank")), 138 | 139 | p(strong("Website:"), a("http://www.theswarmlab.com", 140 | href = "http://www.theswarmlab.com", 141 | target = "_blank")), 142 | 143 | p(strong("Source code:"), 144 | a("GitHub", 145 | href = "https://github.com/swarm-lab/teachR/tree/master/inst/apps/ant_collective_decision", 146 | target = "_blank")), 147 | 148 | p(strong("Created with:"), 149 | a("RStudio", 150 | href = "http://www.rstudio.com/", 151 | target = "_blank"), 152 | " and ", 153 | a("Shiny.", 154 | href = "http://shiny.rstudio.com", 155 | target = "_blank")), 156 | 157 | p(strong("License:"), 158 | a("GPL v3", 159 | href = "http://www.gnu.org/copyleft/gpl.html", 160 | target = "_blank")), 161 | 162 | tags$hr() 163 | ) 164 | ), 165 | 166 | tabPanel(tagList(tags$html("Powered by"), 167 | tags$img(src = "white-rstudio-logo.png", 168 | height = "20")), 169 | value = "RStudio", 170 | tags$head(tags$script(src = "actions.js")) 171 | ) 172 | ) 173 | ) 174 | 175 | 176 | -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/www/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/ant_collective_decision/www/custom.css -------------------------------------------------------------------------------- /inst/apps/ant_collective_decision/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/ant_collective_decision/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/apps/axelrod/info: -------------------------------------------------------------------------------- 1 | Title: Opinion dynamics. 2 | Version: 0.1 3 | Date: 2015-05-13 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the spreading of two competing opinions in an originally uniform population. 7 | Category: Biology, Social Science 8 | Keywords: Opinion dynamics 9 | License: GPL (>= 3) 10 | Depends: ggplot2 (>= 1.0.1), grid (>= 3.2.1), gridExtra (>= 2.0.0), dplyr (>= 0.4.2), scales (>= 0.2.5), simecol (>= 0.8-6), grip 11 | Command: opinion_dynamics -------------------------------------------------------------------------------- /inst/apps/axelrod/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/axelrod/www/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/axelrod/www/custom.css -------------------------------------------------------------------------------- /inst/apps/axelrod/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/axelrod/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/global.R: -------------------------------------------------------------------------------- 1 | #### LOAD LIBRARIES #### 2 | pacman::p_load(shiny, shinythemes, deSolve, plotly, dplyr) 3 | 4 | 5 | #### DEFINE CUSTOM FUNCTIONS #### 6 | #' @title ODE System 7 | #' 8 | #' @description This function represents the ODE system to simulate the 9 | #' collective selection of a nest by honeybee colonies. 10 | #' 11 | #' @param t The time step to compute the ODE at. 12 | #' @param y The values of the state variables of the ODE at the time step. 13 | #' @param parms Parameters of the ODE system. 14 | #' 15 | #' @return A list of the changes in \code{y} suitable for \code{\link{dede}} 16 | #' function. 17 | #' 18 | #' @author Simon Garnier: \email{garnier@@njit.edu}, 19 | #' \link[https://twitter.com/sjmgarnier]{@@sjmgarnier} 20 | #' 21 | ode_sys <- function(t, y, parms) { 22 | yu <- 1 - sum(y) 23 | 24 | dy <- rep(0, 3) 25 | 26 | for (i in 1:3) { 27 | if (i == 3 & t < parms$theta) { 28 | dy[i] <- 0 29 | } else { 30 | idx <- which(1:length(dy) != i) 31 | 32 | dy[i] <- yu * parms$gamma[i] + 33 | y[i] * yu * parms$rho[i] - 34 | y[i] * parms$alpha[i] - 35 | y[i] * sum(parms$sigma[idx] * y[idx]) 36 | } 37 | } 38 | 39 | list(dy) 40 | } 41 | -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/info: -------------------------------------------------------------------------------- 1 | Title: "House hunting" in honeybees. 2 | Version: 0.1 3 | Date: 2015-05-13 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the principle of collective nest selection in honeybees. 7 | Category: Biology 8 | Keywords: Honeybees, Decision-making, Self-Organization 9 | License: GPL (>= 3) 10 | Depends: dplyr (>= 0.4.1), plotly (>= 4.5.6), deSolve (>= 1.11) 11 | Command: bee_house_hunting -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output) { 2 | 3 | res <- reactive({ 4 | parms <- list(gamma = c(input$gamma1, input$gamma2, input$gamma3), # discovery rate 5 | alpha = c(input$alpha1, input$alpha2, input$alpha3), # spontaneous uncommitment 6 | rho = c(input$rho1, input$rho2, input$rho3), # recruitment rate 7 | sigma = c(input$sigma1, input$sigma2, input$sigma3), # conversion rate 8 | theta = input$theta) # time at which 3rd nest is introduced 9 | 10 | tmp <- lsoda(c(0, 0, 0), seq(0, input$duration, 0.05), ode_sys, parms) 11 | tmp[, 2:4] <- tmp[, 2:4] * input$scouts 12 | out <- data.frame(time = rep(tmp[, 1], 3), 13 | nest = rep(c("Nest 1", "Nest 2", "Nest 3"), each = nrow(tmp)), 14 | val = c(tmp[, 2], tmp[, 3], tmp[, 4])) 15 | out 16 | }) 17 | 18 | output$the_display <- renderPlotly({ 19 | g <- ggplot(data = res(), aes(x = time, y = val, color = nest)) + 20 | geom_path(size = 0.75) + 21 | geom_hline(yintercept = input$quorum, size = 0.5, linetype = 2) + 22 | theme_minimal(base_size = 16) + 23 | theme(legend.title = element_blank()) + 24 | xlab("Time") + ylab("Number of committed scouts") + 25 | scale_color_manual(values = c("#2678B2", "#FD7F28", "#339734")) 26 | 27 | ggplotly(g) %>% 28 | layout(legend = list(x = 0.5, y = 1.1, orientation = "h", xanchor = "center"), 29 | hovermode = "x") 30 | }) 31 | 32 | }) 33 | -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI( 2 | navbarPage( 3 | title = "\"House hunting\" in honeybees", 4 | theme = shinytheme("cosmo"), 5 | fluid = FALSE, 6 | collapsible = TRUE, 7 | 8 | tabPanel("Model", 9 | 10 | includeCSS("www/custom.css"), 11 | 12 | # Sidebar 13 | sidebarLayout( 14 | sidebarPanel( 15 | width = 3, 16 | 17 | sliderInput("duration", "Duration of the trial:", 18 | min = 1, max = 200, value = 200, width = "100%"), 19 | sliderInput("scouts", "Number of scouts:", 20 | min = 1, max = 200, value = 100, width = "100%"), 21 | sliderInput("quorum", "Quorum number:", 22 | min = 1, max = 200, value = 25, width = "100%"), 23 | sliderInput("theta", "Time to introduce a 3rd nest:", 24 | min = 1, max = 200, value = 100, width = "100%") 25 | ), 26 | 27 | # Main panel 28 | mainPanel( 29 | fluidRow( 30 | id = "the_display_row", 31 | column(12, plotlyOutput("the_display", height = "100%")) 32 | ), 33 | 34 | fluidRow( 35 | column(4, 36 | wellPanel(h5("Nest #1"), 37 | sliderInput("gamma1", "Discovery rate:", 38 | min = 0, max = 10, value = 1.5, step = 0.1), 39 | sliderInput("alpha1", "Desertion rate:", 40 | min = 0, max = 10, value = 1, step = 0.1), 41 | sliderInput("rho1", "Recruitment rate:", 42 | min = 0, max = 10, value = 2, step = 0.1), 43 | sliderInput("sigma1", "Deconversion rate:", 44 | min = 0, max = 10, value = 2, step = 0.1)) 45 | ), 46 | column(4, 47 | wellPanel(h5("Nest #2"), 48 | sliderInput("gamma2", "Discovery rate:", 49 | min = 0, max = 10, value = 2, step = 0.1), 50 | sliderInput("alpha2", "Desertion rate:", 51 | min = 0, max = 10, value = 1.5, step = 0.1), 52 | sliderInput("rho2", "Recruitment rate:", 53 | min = 0, max = 10, value = 2, step = 0.1), 54 | sliderInput("sigma2", "Deconversion rate:", 55 | min = 0, max = 10, value = 2, step = 0.1)) 56 | ), 57 | column(4, 58 | wellPanel(h5("Nest #3"), 59 | sliderInput("gamma3", "Discovery rate:", 60 | min = 0, max = 10, value = 2, step = 0.1), 61 | sliderInput("alpha3", "Desertion rate:", 62 | min = 0, max = 10, value = 1, step = 0.1), 63 | sliderInput("rho3", "Recruitment rate:", 64 | min = 0, max = 10, value = 2, step = 0.1), 65 | sliderInput("sigma3", "Deconversion rate:", 66 | min = 0, max = 10, value = 2, step = 0.1)) 67 | ) 68 | ) 69 | ) 70 | ) 71 | ), 72 | 73 | tabPanel("Instructions"), 74 | 75 | tabPanel("About", 76 | 77 | fluidRow( 78 | tags$hr(), 79 | 80 | p(strong("Author:"), " Simon Garnier (", a("New Jersey Institute of Technology", 81 | href = "http://www.njit.edu", 82 | target = "_blank"), ")"), 83 | 84 | p(strong("Twitter:"), a("@sjmgarnier", 85 | href = "https://twitter.com/sjmgarnier", 86 | target = "_blank")), 87 | 88 | p(strong("Website:"), a("http://www.theswarmlab.com", 89 | href = "http://www.theswarmlab.com", 90 | target = "_blank")), 91 | 92 | p(strong("Source code:"), 93 | a("GitHub", 94 | href = "https://github.com/swarm-lab/teachR/tree/master/inst/apps/bee_house_hunting", 95 | target = "_blank")), 96 | 97 | p(strong("Created with:"), 98 | a("RStudio", 99 | href = "http://www.rstudio.com/", 100 | target = "_blank"), 101 | " and ", 102 | a("Shiny.", 103 | href = "http://shiny.rstudio.com", 104 | target = "_blank")), 105 | 106 | p(strong("License:"), 107 | a("GPL v3", 108 | href = "http://www.gnu.org/copyleft/gpl.html", 109 | target = "_blank")), 110 | 111 | tags$hr() 112 | ) 113 | ), 114 | 115 | tabPanel(tagList(tags$html("Powered by"), 116 | tags$img(src = "white-rstudio-logo.png", 117 | height="20")), 118 | value = "RStudio", 119 | tags$head(tags$script(src = "actions.js")) 120 | ) 121 | ) 122 | ) 123 | -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/www/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/bee_house_hunting/www/custom.css -------------------------------------------------------------------------------- /inst/apps/bee_house_hunting/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/bee_house_hunting/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/global.R: -------------------------------------------------------------------------------- 1 | pacman::p_load(shiny, shinythemes, simecol, ggvis, dplyr) 2 | 3 | grid_sys <- function(time, init, parms) { 4 | o1 <- init 5 | o1[o1 < 0] <- 0 6 | 7 | o2 <- init 8 | o2[o2 > 0] <- 0 9 | 10 | p1 <- eightneighbors(o1) / 8 11 | p2 <- p1 - eightneighbors(o2) / 8 12 | 13 | r <- runif(nrow(init) * ncol(init)) 14 | 15 | idx1 <- r <= p1 16 | idx2 <- r <= p2 & r > p1 17 | 18 | init[idx1] <- 1 * parms$w1 19 | init[idx2] <- -1 * parms$w2 20 | 21 | init 22 | } 23 | -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/info: -------------------------------------------------------------------------------- 1 | Title: Opinion dynamics. 2 | Version: 0.1 3 | Date: 2015-05-13 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the spreading of two competing opinions in an originally uniform population. 7 | Category: Biology, Social Science 8 | Keywords: Opinion dynamics 9 | License: GPL (>= 3) 10 | Depends: dplyr (>= 0.4.2), simecol (>= 0.8-6), ggvis (>= 0.4.3) 11 | Command: opinion_dynamics -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output, session) { 2 | data <- reactiveValues() 3 | 4 | observe({ 5 | input$rerun 6 | 7 | mat <- matrix(0, nrow = 25, ncol = 25) 8 | mat[sample(1:(25 * 25), 2, FALSE)] <- c(1, -1) 9 | 10 | m1 <- new("gridModel", main = grid_sys, parms = list(w1 = input$w1, w2 = input$w2), 11 | times = 0:input$max.time, init = mat, solver = "iteration") 12 | 13 | data$steps <- out(sim(m1)) 14 | 15 | data$summary <- data.frame(time = 0:input$max.time, 16 | s1 = sapply(data$steps, function(x) sum(x > 0)), 17 | s2 = sapply(data$steps, function(x) sum(x < 0))) 18 | }) 19 | 20 | output$timeline <- renderUI({ 21 | sliderInput("time", "Timeline (move cursor or click on play button)", 22 | min = 0, max = input$max.time, value = 0, step = 1, width = "100%", 23 | animate = animationOptions(interval = 250, loop = FALSE, 24 | playButton = tag("span", list(class = "glyphicon glyphicon-play")), 25 | pauseButton = tag("span", list(class = "glyphicon glyphicon-pause")))) 26 | }) 27 | 28 | observe({ 29 | if (is.null(input$time)) { 30 | return() 31 | } 32 | 33 | data.frame(expand.grid(x = 1:25, y = 1:25), 34 | z = sign(as.vector(data$steps[[input$time + 1]])) + 2) %>% 35 | mutate(color = c("#1E90FF", "#FFFFFF", "#FF6347")[z]) %>% 36 | ggvis(x = ~factor(x), y = ~factor(y), fill := ~color) %>% 37 | layer_rects(width = band(), height = band(), strokeWidth := 0.1) %>% 38 | hide_axis("x") %>% 39 | hide_axis("y") %>% 40 | hide_legend("fill") %>% 41 | set_options(width = "auto", height = "100%", resizable = FALSE, duration = 30) %>% 42 | bind_shiny("display1") 43 | 44 | filter(data$summary, time <= (input$time + 1)) %>% 45 | ggvis(x = ~time) %>% 46 | layer_paths(y = ~100 * (25 * 25 - s1 - s2) / 625, stroke := "black", strokeWidth := 2) %>% 47 | layer_paths(y = ~100 * s1 / 625, stroke := "tomato", strokeWidth := 2) %>% 48 | layer_paths(y = ~100 * s2 / 625, stroke := "dodgerblue", strokeWidth := 2) %>% 49 | scale_numeric("x", domain = c(0, input$max.time), nice = FALSE) %>% 50 | add_axis("x", title = "Time") %>% 51 | add_axis("y", title = "% population") %>% 52 | set_options(width = "auto", height = "100%", resizable = FALSE, duration = 30) %>% 53 | bind_shiny("display2") 54 | }) 55 | }) 56 | 57 | 58 | -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI( 2 | navbarPage( 3 | title = "Opinion dynamics", 4 | theme = shinytheme("cosmo"), 5 | fluid = FALSE, 6 | collapsible = TRUE, 7 | 8 | tabPanel("Model", 9 | 10 | includeCSS("www/custom.css"), 11 | 12 | # Sidebar 13 | sidebarLayout( 14 | sidebarPanel( 15 | width = 3, 16 | sliderInput("max.time", "Duration of the trial:", 17 | min = 1, max = 500, value = 200, width = "100%"), 18 | sliderInput("w1", "Strength of opinion 1:", 19 | min = 0, max = 1, value = 0.25, step = 0.01, width = "100%"), 20 | sliderInput("w2", "Strength of opinion 2:", 21 | min = 0, max = 1, value = 0.25, step = 0.01, width = "100%"), 22 | p(align = 'center', 23 | actionButton("rerun", "Rerun")) 24 | ), 25 | 26 | # Main panel 27 | mainPanel( 28 | fluidRow( 29 | column(6, 30 | tags$div(class = "box", 31 | tags$div(class = "content", 32 | ggvisOutput("display1"))) 33 | # plotOutput("plot", height = "500px") 34 | ), 35 | column(6, 36 | tags$div(class = "box", 37 | tags$div(class = "content", 38 | ggvisOutput("display2"))) 39 | # plotOutput("plot", height = "500px") 40 | ), 41 | uiOutput("timeline")) 42 | ) 43 | ) 44 | ), 45 | 46 | tabPanel("Instructions"), 47 | 48 | tabPanel("About", 49 | 50 | fluidRow( 51 | tags$hr(), 52 | 53 | p(strong("Author:"), " Simon Garnier (", a("New Jersey Institute of Technology", 54 | href = "http://www.njit.edu", 55 | target = "_blank"), ")"), 56 | 57 | p(strong("Twitter:"), a("@sjmgarnier", 58 | href = "https://twitter.com/sjmgarnier", 59 | target = "_blank")), 60 | 61 | p(strong("Website:"), a("http://www.theswarmlab.com", 62 | href = "http://www.theswarmlab.com", 63 | target = "_blank")), 64 | 65 | p(strong("Source code:"), 66 | a("GitHub", 67 | href = "https://github.com/swarm-lab/teachR/tree/master/inst/apps/opinion_dynamics", 68 | target = "_blank")), 69 | 70 | p(strong("Created with:"), 71 | a("RStudio", 72 | href = "http://www.rstudio.com/", 73 | target = "_blank"), 74 | " and ", 75 | a("Shiny.", 76 | href = "http://shiny.rstudio.com", 77 | target = "_blank")), 78 | 79 | p(strong("License:"), 80 | a("GPL v3", 81 | href = "http://www.gnu.org/copyleft/gpl.html", 82 | target = "_blank")), 83 | 84 | tags$hr() 85 | ) 86 | ), 87 | 88 | tabPanel(tagList(tags$html("Powered by"), 89 | tags$img(src = "white-rstudio-logo.png", 90 | height = "20")), 91 | value = "RStudio", 92 | tags$head(tags$script(src = "actions.js")) 93 | ) 94 | ) 95 | ) 96 | -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/www/custom.css: -------------------------------------------------------------------------------- 1 | .box{ 2 | position: relative; 3 | width: 100%; /* desired width */ 4 | } 5 | 6 | .box:before{ 7 | content: ""; 8 | display: block; 9 | padding-top: 100%; /* initial ratio of 1:1*/ 10 | } 11 | 12 | .content { 13 | position: absolute; 14 | top: 0; 15 | left: 0; 16 | bottom: 0; 17 | right: 0; 18 | } 19 | -------------------------------------------------------------------------------- /inst/apps/opinion_dynamics/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/opinion_dynamics/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/global.R: -------------------------------------------------------------------------------- 1 | pacman::p_load(shiny, shinythemes, dplyr, plotly, compiler, memoise, msm) 2 | 3 | enableJIT(3) 4 | 5 | memoise(sigmoid <- function(x, a = 0, k = 1, b = 0.1, m = 100, v = 1, q = 1) { 6 | s <- a + (k - a) / ((1 + q * exp(-b * (x - m))) ^ (1 / v)) 7 | s0 <- a + (k - a) / ((1 + q * exp(-b * (0 - m))) ^ (1 / v)) 8 | (s - s0) / diff(c(s0, 1)) * diff(c(0, 1)) 9 | }) 10 | 11 | memoise(woc <- function(n = 100, val = 200, error = 0.1, soc = 1) { 12 | res <- rtnorm(n, mean = val, sd = val * error, lower = 0) 13 | soc <- sigmoid(0:n, m = (1 - soc) * n, b = 0.5) 14 | 15 | for (i in 2:n) { 16 | res[i] <- res[i] * (1 - soc[i]) + mean(res[1:(i - 1)]) * soc[i] 17 | } 18 | 19 | res 20 | }) 21 | -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/info: -------------------------------------------------------------------------------- 1 | Title: The Wisdom of Crowds. 2 | Version: 0.1 3 | Date: 2016-02-10 4 | Author: Simon Garnier 5 | Maintainer: Simon Garnier 6 | Description: This app illustrates the 'Wisdom of Crowds' effect and what happens when social interactions are allowed to happen between the actors. 7 | Category: Biology, Social Science 8 | Keywords: Opinion dynamics 9 | License: GPL (>= 3) 10 | Depends: plotly, dplyr, compiler, memoise, msm 11 | Command: wisdom_of_crowds -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output, session) { 2 | 3 | react <- reactiveValues(tab = {}, count = -1) 4 | 5 | observe({ 6 | if (react$count != input$goButton) { 7 | react$count <- input$goButton 8 | 9 | withProgress(message = paste0("Simulating ", input$rep, " experiments"), { 10 | m1 <- replicate(input$rep, woc(n = input$n, 11 | val = 200, 12 | error = input$error / 100, 13 | soc = 0)) 14 | tmp1 <- abs(m1 - 200) 15 | tmp2 <- abs(matrix(apply(m1, 2, mean), nrow = input$n, ncol = input$rep, byrow = TRUE) - 200) 16 | r1 <- apply(tmp2 < tmp1, 2, sum) 17 | 18 | m2 <- replicate(input$rep, woc(n = input$n, 19 | val = 200, 20 | error = input$error / 100, 21 | soc = input$soc)) 22 | tmp1 <- abs(m2 - 200) 23 | tmp2 <- abs(matrix(apply(m2, 2, mean), nrow = input$n, ncol = input$rep, byrow = TRUE) - 200) 24 | r2 <- apply(tmp2 < tmp1, 2, sum) 25 | 26 | react$tab <- data.frame( 27 | SOC = as.factor(rep(c("Control", "Experimental"), each = input$rep * 2)), 28 | TYPE = rep(c("mean", "sd", "mean", "sd"), each = input$rep), 29 | VAL = c(apply(m1, 2, mean), # 100 * (r1 / input$n), 30 | apply(m1, 2, sd), 31 | apply(m2, 2, mean), # 100 * (r2 / input$n), 32 | apply(m2, 2, sd))) 33 | }) 34 | } 35 | }) 36 | 37 | output$IBM.plot1 <- renderPlotly({ 38 | sub_dat <- filter(react$tab, TYPE == "mean") 39 | r <- c(min(sub_dat$VAL), max(sub_dat$VAL)) 40 | plot_ly(sub_dat, type = "histogram", alpha = 0.6, 41 | x = ~VAL, color = ~SOC, colors = c("tomato3", "dodgerblue3"), 42 | xbins = list(start = r[1], end = r[2], size = diff(r) / 40), 43 | autobinx = FALSE) %>% 44 | layout(barmode = "overlay", hovermode = "x", 45 | xaxis = list(title = "Group average"), 46 | yaxis = list(title = "Count"), 47 | font = list(size = 14), 48 | legend = list(x = 0.5, y = 1.1, orientation = "h", xanchor = "center")) 49 | }) 50 | 51 | output$IBM.plot2 <- renderPlotly({ 52 | sub_dat <- filter(react$tab, TYPE == "sd") 53 | r <- c(min(sub_dat$VAL), max(sub_dat$VAL)) 54 | plot_ly(sub_dat, type = "histogram", alpha = 0.6, 55 | x = ~VAL, color = ~SOC, colors = c("tomato3", "dodgerblue3"), 56 | xbins = list(start = r[1], end = r[2], size = diff(r) / 40), 57 | autobinx = FALSE) %>% 58 | layout(barmode = "overlay", hovermode = "x", 59 | xaxis = list(title = "Group standard deviation"), 60 | yaxis = list(title = "Count"), 61 | font = list(size = 14), 62 | legend = list(x = 0.5, y = 1.1, orientation = "h", xanchor = "center")) 63 | }) 64 | }) 65 | -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI( 2 | navbarPage( 3 | title = "The Wisdom of Crowds", 4 | theme = shinytheme("cosmo"), 5 | fluid = FALSE, 6 | collapsible = TRUE, 7 | 8 | tabPanel("Model", 9 | 10 | includeCSS("www/custom.css"), 11 | 12 | # Sidebar 13 | sidebarLayout( 14 | sidebarPanel( 15 | width = 3, 16 | 17 | sliderInput("n", "Number of individuals in the group", 18 | min = 50, max = 500, value = 100, step = 1, width = "100%"), hr(), 19 | 20 | sliderInput("error", "% error of individual guesses", 21 | min = 0, max = 100, value = 20, width = "100%"), hr(), 22 | 23 | sliderInput("soc", "Intensity of social influence", 24 | min = 0, max = 1, value = 0, width = "100%"), hr(), 25 | 26 | sliderInput("rep", "Number of replicates", 27 | min = 0, max = 1000, value = 500, width = "100%"), hr(), 28 | 29 | div(style = "text-align: center;", 30 | actionButton("goButton", "Rerun", icon = icon("refresh")) 31 | ) 32 | 33 | ), 34 | 35 | # Main panel 36 | mainPanel( 37 | fluidRow( 38 | column(6, 39 | plotlyOutput("IBM.plot1", height = "100%")), 40 | 41 | column(6, 42 | plotlyOutput("IBM.plot2", height = "100%")) 43 | ), 44 | 45 | tags$hr(), 46 | 47 | p(tags$b("Control"), " = no social influence"), 48 | p(tags$b("Experimental"), " = social influence set to slider value"), 49 | p(tags$b("Number of gumballs"), " = 200") 50 | ) 51 | ) 52 | ), 53 | 54 | tabPanel("Instructions", 55 | 56 | fluidRow( 57 | tags$hr(), 58 | 59 | h2("Goal"), 60 | 61 | p("This webapp simulates a classical experiment in the social 62 | sciences that aims at demonstrating the so-called 'Wisdom of 63 | Crowds'."), 64 | 65 | p("In this experiment, a number of people (set by the user) are 66 | asked to guess the number of gumballs placed in a jar. Each 67 | guess is likely to be off the true number of gumballs in the 68 | jar. However, if all the guesses are made independently and in 69 | the absence of general perceptual or cognitive bias to 70 | systematically under- or overestimate this number, the average 71 | guess of the group will be close to the exact number of 72 | gumballs. This observation, ", a("made originally by Sir Francis 73 | Galton in 1906", 74 | href = "https://en.wikipedia.org/wiki/Francis_Galton#Variance_and_standard_deviation"), 75 | ", is at the origin of concept of 'Wisdom of Crowds', where the 76 | crowd as a whole is better than any of the people who compose 77 | it"), 78 | 79 | p("However, if the guesses are not made independently (e.g. if 80 | each person knows about previous guesses), then things can get 81 | quickly out of hands, and the 'Wisdom of Crowds' disappear. 82 | The goal of this simulation if to help you understand how 83 | social feedback (i.e. knowledge of other people's guesses in 84 | this case) can undermine the ability of a group to act as a 85 | reliable collective estimator."), 86 | 87 | tags$hr(), 88 | 89 | h2("Parameters"), 90 | 91 | p("This simulation takes 3 parameters that you can modify using 92 | the sliders in the 'Model' tab."), 93 | 94 | tags$ol( 95 | tags$li(tags$b("Number of individuals in the group: "), "this 96 | sets the number of people who are asked to guess in 97 | each replicate of the virtual experiment."), 98 | tags$li(tags$b("% error of individual guesses: "), "this sets 99 | the average error of each person's guess. For instance, 100 | if sets to 20%, this means that people make guesses 101 | that in average 20% off the real number of gumballs in 102 | the jar (above or below this number)."), 103 | tags$li(tags$b("Intensity of social influence: "), "this 104 | determines how much each individual cares about the 105 | guesses made by previous individuals. If set to 0, it 106 | means that they ignore them completely before making a 107 | guess (independent guesses).") 108 | ), 109 | 110 | p("Every time you re-run the experiment with a different set of 111 | parameters, the software simulates 1,000 replicates."), 112 | 113 | tags$hr(), 114 | 115 | h2("Outputs"), 116 | 117 | p("This simulation returns 2 graphs."), 118 | 119 | tags$ol( 120 | tags$li("The left represents the percentage of individuals in 121 | each replicate that made a worse guess that the group's 122 | average in that replicate. Higher values indicates that 123 | the group performs better than most of its members."), 124 | tags$li("The right graph represents the distribution of the 125 | groups' standard deviations. Smaller values indicates 126 | that individual opinions are more similar to each other.") 127 | ), 128 | 129 | tags$hr() 130 | ) 131 | ), 132 | 133 | tabPanel("About", 134 | 135 | fluidRow( 136 | tags$hr(), 137 | 138 | p(strong("Author:"), " Simon Garnier (", a("New Jersey Institute of Technology", 139 | href = "http://www.njit.edu", 140 | target = "_blank"), ")"), 141 | 142 | p(strong("Twitter:"), a("@sjmgarnier", 143 | href = "https://twitter.com/sjmgarnier", 144 | target = "_blank")), 145 | 146 | p(strong("Website:"), a("http://www.theswarmlab.com", 147 | href = "http://www.theswarmlab.com", 148 | target = "_blank")), 149 | 150 | p(strong("Source code:"), 151 | a("GitHub", 152 | href = "https://github.com/swarm-lab/Shiny/tree/master/wisdom_of_crowds/model", 153 | target = "_blank")), 154 | 155 | p(strong("Created with:"), 156 | a("RStudio", 157 | href = "http://www.rstudio.com/", 158 | target = "_blank"), 159 | " and ", 160 | a("Shiny.", 161 | href = "http://shiny.rstudio.com", 162 | target = "_blank")), 163 | 164 | p(strong("License:"), 165 | a("GPL v3", 166 | href = "http://www.gnu.org/copyleft/gpl.html", 167 | target = "_blank")), 168 | 169 | tags$hr() 170 | ) 171 | ), 172 | 173 | tabPanel(tagList(tags$html("Powered by"), 174 | tags$img(src = "white-rstudio-logo.png", 175 | height = "20")), 176 | value = "RStudio", 177 | tags$head(tags$script(src = "actions.js")) 178 | ) 179 | ) 180 | ) 181 | 182 | -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/www/actions.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | 3 | jQuery(function($){ 4 | $("a[data-value='RStudio']").attr("href", "http://www.rstudio.com"); 5 | $("a[data-value='RStudio']").attr("data-toggle", ""); 6 | }); 7 | 8 | }); 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/www/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/wisdom_of_crowds/www/custom.css -------------------------------------------------------------------------------- /inst/apps/wisdom_of_crowds/www/white-rstudio-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/inst/apps/wisdom_of_crowds/www/white-rstudio-logo.png -------------------------------------------------------------------------------- /inst/html_templates/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Apps available in teachR 7 | 8 | 19 | 20 | #!r_highlight# 21 | 22 | #!mathjax# 23 | 24 | 47 | 48 | 49 | 50 | #!header# 51 | 52 | 53 | 54 | 55 |

    #!title#

    56 |
    57 | #!html_output# 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/logo.png -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 11 | 12 | 13 | teachR 14 | 15 | 16 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /man/export_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/export_app.R 3 | \name{export_app} 4 | \alias{export_app} 5 | \title{Export \code{teachR} Apps} 6 | \usage{ 7 | export_app(app, dest) 8 | } 9 | \arguments{ 10 | \item{app}{The name of the app to export.} 11 | 12 | \item{dest}{The destination of the app folder on the user's computer. A folder 13 | with the name of the app will be created at this location.} 14 | } 15 | \value{ 16 | This function does not return anything. 17 | } 18 | \description{ 19 | This function exports a Shiny app provided by the 20 | \code{teachR} library to a local folder on 21 | a user's computer. Useful for modifying the app or running it on a Shiny 22 | Server instance for example. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | # Export app to the current working directory 27 | export_app("aggregation_segregation", ".") 28 | } 29 | 30 | } 31 | \author{ 32 | Simon Garnier, \email{garnier@njit.edu} 33 | } 34 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/man/figures/logo.png -------------------------------------------------------------------------------- /man/list_apps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/list_apps.R 3 | \name{list_apps} 4 | \alias{list_apps} 5 | \title{List \code{teachR} Apps} 6 | \usage{ 7 | list_apps(categories = NULL, keywords = NULL) 8 | } 9 | \arguments{ 10 | \item{categories}{A character string or a vector of character strings 11 | corresponding to existing app categories (case insensitive).} 12 | 13 | \item{keywords}{A character string or a vector of character strings 14 | corresponding to existing app keywords (case insensitive).} 15 | } 16 | \value{ 17 | This function opens an html file. 18 | } 19 | \description{ 20 | This function generates a webpage listing all the apps available 21 | through the \code{teachR} library. The list can be filtered by category 22 | (type \code{list_categories()} for a list of existing categories) and 23 | keywords (type \code{list_keywords()} for a list of existing keywords). 24 | } 25 | \details{ 26 | If called from RStudio, the list will open in the internal RStudio 27 | viewer. If called from a terminal, it will open in your default internet 28 | browser. 29 | } 30 | \examples{ 31 | \dontrun{ 32 | list_apps(categories = c("biology", "social science")) 33 | } 34 | 35 | } 36 | \author{ 37 | Simon Garnier, \email{garnier@njit.edu} 38 | } 39 | -------------------------------------------------------------------------------- /man/list_categories.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/list_categories.R 3 | \name{list_categories} 4 | \alias{list_categories} 5 | \title{List Categories of All \code{teachR} Apps} 6 | \usage{ 7 | list_categories() 8 | } 9 | \value{ 10 | A vector of character strings, each of them corresponding to a different 11 | category. 12 | } 13 | \description{ 14 | This function generates a listing of all the categories of apps 15 | available through the \code{teachR} library. 16 | } 17 | \examples{ 18 | \dontrun{ 19 | list_categories() 20 | } 21 | 22 | } 23 | \author{ 24 | Simon Garnier, \email{garnier@njit.edu} 25 | } 26 | -------------------------------------------------------------------------------- /man/list_keywords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/list_keywords.R 3 | \name{list_keywords} 4 | \alias{list_keywords} 5 | \title{List Keywords of All \code{teachR} Apps} 6 | \usage{ 7 | list_keywords() 8 | } 9 | \value{ 10 | A vector of character strings, each of them corresponding to a different 11 | keyword. 12 | } 13 | \description{ 14 | This function generates a listing of all the keywords of apps 15 | available through the \code{teachR} library. 16 | } 17 | \examples{ 18 | \dontrun{ 19 | list_keywords() 20 | } 21 | 22 | } 23 | \author{ 24 | Simon Garnier, \email{garnier@njit.edu} 25 | } 26 | -------------------------------------------------------------------------------- /man/run_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/run_app.R 3 | \name{run_app} 4 | \alias{run_app} 5 | \title{Run \code{teachR} Apps} 6 | \usage{ 7 | run_app(app) 8 | } 9 | \arguments{ 10 | \item{app}{The name of the app to run.} 11 | } 12 | \value{ 13 | This function does not return anything. 14 | } 15 | \description{ 16 | This function calls a Shiny app provided by the 17 | \code{teachR} library. The list of available Shiny apps can be obtained by 18 | typing \code{list_apps()} in your R terminal. 19 | } 20 | \details{ 21 | If called from RStudio, the app will open in the internal RStudio 22 | internet browser. If called from a terminal, it will open in your default 23 | internet browser. All apps should work without any problem with the internal 24 | RStudio internet browser, as well as with recent versions of most internet 25 | browsers. It is likely to break with older versions. 26 | } 27 | \examples{ 28 | \dontrun{ 29 | run_app("aggregation_segregation") 30 | } 31 | 32 | } 33 | \author{ 34 | Simon Garnier, \email{garnier@njit.edu} 35 | } 36 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swarm-lab/teachR/07583fc5cb9e2d6dcb9ba2b13ab6099e7292ea1d/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /teachR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | PackageRoxygenize: rd,collate,namespace,vignette 19 | -------------------------------------------------------------------------------- /vignettes/z1_install.R: -------------------------------------------------------------------------------- 1 | ## ---- message=FALSE, eval=FALSE------------------------------------------ 2 | # if (!require(devtools)) 3 | # install.packages("devtools") 4 | 5 | ## ---- message=FALSE, eval=FALSE------------------------------------------ 6 | # devtools::install_github("swarm-lab/teachR") 7 | 8 | ## ---- message=FALSE, eval=FALSE------------------------------------------ 9 | # library(teachR) 10 | 11 | -------------------------------------------------------------------------------- /vignettes/z1_install.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1 - Installing teachR" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{pkgdown} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | __This page describes the installation process of [`teachR`](https://github.com/swarm-lab/teachR).__ 11 | 12 | `teachR` has not been released on [CRAN](https://cran.r-project.org/) yet, but it 13 | can be easily installed from its [GitHub repository](https://github.com/swarm-lab/teachR) 14 | with the following steps. 15 | 16 | --- 17 | 18 | + [1.1 - Before installing ](#before-installing) 19 | + [1.2 - Installing teachR](#installing-teachr) 20 | + [1.3 - Loading teachR](#loading-teachr) 21 | 22 | --- 23 | 24 | ## 1.1 - Before installing 25 | 26 | Before installing `teachR`, you will need to install the latest version of the [`devtools`](https://CRAN.R-project.org/package=devtools) package. You can install [`devtools`](https://CRAN.R-project.org/package=devtools) from 27 | [`CRAN`](https://cran.r-project.org) as follows: 28 | 29 | ```{r, message=FALSE, eval=FALSE} 30 | if (!require(devtools)) 31 | install.packages("devtools") 32 | ``` 33 | 34 | --- 35 | 36 | ## 1.2 - Installing teachR 37 | 38 | You can install `teachR` as follows: 39 | 40 | ```{r, message=FALSE, eval=FALSE} 41 | devtools::install_github("swarm-lab/teachR") 42 | ``` 43 | 44 | --- 45 | 46 | ## 1.3 - Loading teachR 47 | 48 | ```{r, message=FALSE, eval=FALSE} 49 | library(teachR) 50 | ``` 51 | -------------------------------------------------------------------------------- /vignettes/z2_usage.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1 - Installing teachR" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{pkgdown} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | __This page describes how to use [`teachR`](https://github.com/swarm-lab/teachR).__ 11 | -------------------------------------------------------------------------------- /vignettes/z2_usage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 1 - Installing teachR 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |

    1 - Installing teachR

    32 | 33 | 34 | 35 |

    This page describes how to use teachR.

    36 | 37 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /vignettes/z3_participate.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "1 - Installing teachR" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{pkgdown} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | __This page describes how to add apps to [`teachR`](https://github.com/swarm-lab/teachR).__ 11 | -------------------------------------------------------------------------------- /vignettes/z3_participate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 1 - Installing teachR 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |

    1 - Installing teachR

    32 | 33 | 34 | 35 |

    This page describes how to add apps to teachR.

    36 | 37 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | --------------------------------------------------------------------------------