├── LICENSE
├── .gitignore
├── tests
├── testthat.R
└── testthat
│ └── test-package.R
├── img
├── open-data-bingo.png
├── bingo-01-open-data.png
└── bingo-01-superbowl-50-2016.png
├── NAMESPACE
├── .travis.yml
├── .Rbuildignore
├── codecov.yml
├── man
├── launch.Rd
├── get_topics.Rd
├── get_topic.Rd
├── bingo.Rd
└── plot.bingo.Rd
├── R
├── Colors.R
├── launch.R
├── utils.R
├── Eurovision_bingo.R
├── topics.R
└── bingo.R
├── bingo.Rproj
├── inst
├── topics
│ ├── MN_backyardLife.R
│ ├── Random_Bike_Topics.R
│ ├── IndianaGeology.R
│ ├── july4th.R
│ ├── Bingo_Flowers.R
│ ├── game-of-thrones.R
│ ├── iowa.R
│ ├── dorm-room.R
│ ├── WeeklyJump.R
│ ├── math-proofs.R
│ ├── boring-meeting.R
│ ├── csama.R
│ ├── open-data.R
│ ├── news-nerd.R
│ ├── conference-call.R
│ ├── manuscript-review.R
│ ├── stat-ecology.R
│ ├── bad-data.R
│ ├── useR-conf.R
│ ├── olympic-sports.R
│ └── football.R
└── shiny
│ ├── www
│ └── app.css
│ ├── global.R
│ ├── server.R
│ └── ui.R
├── DESCRIPTION
├── CONTRIBUTING.md
├── appveyor.yml
├── README.Rmd
└── README.md
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2016
2 | COPYRIGHT HOLDER: Jennifer Bryan
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | bingo-*.pdf
5 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(bingo)
3 |
4 | test_check("bingo")
5 |
--------------------------------------------------------------------------------
/img/open-data-bingo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jennybc/bingo/HEAD/img/open-data-bingo.png
--------------------------------------------------------------------------------
/img/bingo-01-open-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jennybc/bingo/HEAD/img/bingo-01-open-data.png
--------------------------------------------------------------------------------
/img/bingo-01-superbowl-50-2016.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jennybc/bingo/HEAD/img/bingo-01-superbowl-50-2016.png
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method(plot,bingo)
4 | export(bingo)
5 | export(get_topic)
6 | export(get_topics)
7 | export(launch)
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r
2 |
3 | language: R
4 | cache: packages
5 |
6 | after_success:
7 | - Rscript -e 'covr::codecov()'
8 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^\.travis\.yml$
2 | ^.*\.Rproj$
3 | ^\.Rproj\.user$
4 | ^README\.Rmd$
5 | ^README-.*\.png$
6 | ^bingo-.*\.pdf$
7 | ^img$
8 | ^CONTRIBUTING\.md$
9 | ^codecov\.yml$
10 | ^appveyor\.yml$
11 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: false
2 |
3 | coverage:
4 | status:
5 | project:
6 | default:
7 | target: auto
8 | threshold: 1%
9 | patch:
10 | default:
11 | target: auto
12 | threshold: 1%
13 |
--------------------------------------------------------------------------------
/man/launch.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/launch.R
3 | \name{launch}
4 | \alias{launch}
5 | \title{Launch the Shiny app that generates bingo cards}
6 | \usage{
7 | launch()
8 | }
9 | \description{
10 | Launch the Shiny app that generates bingo cards
11 | }
12 |
--------------------------------------------------------------------------------
/R/Colors.R:
--------------------------------------------------------------------------------
1 | c("pink",
2 | "purple",
3 | "blue",
4 | "green",
5 | "orange",
6 | "yellow",
7 | "chartreuse",
8 | "turquoise",
9 | "brown",
10 | "black",
11 | "white",
12 | "peach",
13 | "lilac",
14 | "gray",
15 | "periwinkle",
16 | "beige",
17 | "silver",
18 | "gold",
19 | "bronze",
20 | "charcoal",
21 | "burgundy",
22 | "olive",
23 | "lime",
24 | "lemon")
25 |
--------------------------------------------------------------------------------
/man/get_topics.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/topics.R
3 | \name{get_topics}
4 | \alias{get_topics}
5 | \title{Get all bingo card topics}
6 | \usage{
7 | get_topics()
8 | }
9 | \value{
10 | A character vector containing the names of all the bingo card topics
11 | }
12 | \description{
13 | Get all bingo card topics
14 | }
15 | \examples{
16 | get_topics()
17 | }
18 |
--------------------------------------------------------------------------------
/bingo.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: No
4 | SaveWorkspace: No
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 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageRoxygenize: rd,collate,namespace
22 |
--------------------------------------------------------------------------------
/man/get_topic.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/topics.R
3 | \name{get_topic}
4 | \alias{get_topic}
5 | \title{Get the words of a bingo card topic}
6 | \usage{
7 | get_topic(topic)
8 | }
9 | \arguments{
10 | \item{topic}{Name of a topic (a string)}
11 | }
12 | \value{
13 | A character vector containing all the possible words of a bingo card
14 | topic
15 | }
16 | \description{
17 | Get the words of a bingo card topic
18 | }
19 | \examples{
20 | get_topic("open-data")
21 | }
22 |
--------------------------------------------------------------------------------
/inst/topics/MN_backyardLife.R:
--------------------------------------------------------------------------------
1 | ## Aim : bingo card proposal for animals
2 | ## Author : Larissa Stanberry
3 | c('cat',
4 | 'dog',
5 | 'snapping turtle',
6 | 'painted turtle',
7 | 'muskrat',
8 | 'mallard duck',
9 | 'chipmunk',
10 | 'squirrel',
11 | 'deer',
12 | 'cardinal',
13 | 'red-winged blackbird',
14 | 'blue jay',
15 | 'swan',
16 | 'deer',
17 | 'monarch butterfly',
18 | 'snake',
19 | 'bee',
20 | 'loon',
21 | 'owl',
22 | 'woodpecker',
23 | 'wasp yellow jacket',
24 | 'northern cardinal',
25 | 'eagle',
26 | 'hawk')
27 |
--------------------------------------------------------------------------------
/man/bingo.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/bingo.R
3 | \name{bingo}
4 | \alias{bingo}
5 | \title{Generate bingo cards}
6 | \usage{
7 | bingo(n_cards = 1, words, n = 5)
8 | }
9 | \arguments{
10 | \item{n_cards}{number of cards}
11 |
12 | \item{words}{text for the bingo squares}
13 |
14 | \item{n}{number of rows/columns for one card}
15 | }
16 | \value{
17 | a \code{bingo} object, which is really just a character matrix
18 | }
19 | \description{
20 | Generate bingo cards
21 | }
22 | \examples{
23 | bingo()
24 | }
25 |
--------------------------------------------------------------------------------
/tests/testthat/test-package.R:
--------------------------------------------------------------------------------
1 | context("bingo")
2 |
3 | test_that("duplicate squares are removed", {
4 | x <- c("a", "a", "b")
5 | expect_identical(c("a", "b"), vet_squares(x))
6 | })
7 |
8 |
9 | test_that("each topic contains at least 24 unique values", {
10 | expect_topic_length <- function(topic) {
11 | nt <- length(get_topic(topic))
12 | expect(
13 | nt >= 24,
14 | sprintf("'%s' has length %i", topic, nt)
15 | )
16 | invisible(topic)
17 | }
18 |
19 | topics <- get_topics()
20 | for (t in topics) expect_topic_length(t)
21 | })
22 |
--------------------------------------------------------------------------------
/inst/topics/Random_Bike_Topics.R:
--------------------------------------------------------------------------------
1 | ## Aim : bingo card proposal for bike thoughts
2 | ## Author : Darvish Shadravan
3 |
4 | c(
5 | "Jersey",
6 | "Tires",
7 | "Water Bottle",
8 | "Energy Drink",
9 | "Carbon Frame",
10 | "Mountain Bike",
11 | "Gravel Bike",
12 | "Snow Tires",
13 | "Grips",
14 | "Lycra Shorts",
15 | "Gloves",
16 | "Helmet",
17 | "Race Day",
18 | "Pedals",
19 | "Chain Lube",
20 | "Wind Vest",
21 | "Sunburn",
22 | "Tubeless",
23 | "Beer",
24 | "Pizza",
25 | "Bonk",
26 | "Studded Tires",
27 | "GPS",
28 | "100 miles"
29 | )
30 |
--------------------------------------------------------------------------------
/inst/topics/IndianaGeology.R:
--------------------------------------------------------------------------------
1 | # Indiana Geology themed bingo
2 | c("normal fault",
3 | "crystal lattice",
4 | "beer",
5 | "fold-thrust fault",
6 | "generic carbonate",
7 | "exposure",
8 | "brachiopod",
9 | "trilobite",
10 | "marine facies",
11 | "geode",
12 | "pyrite",
13 | "anticline",
14 | "syncline",
15 | "shale",
16 | "coal seam",
17 | "horn coral",
18 | "bryozoan",
19 | "karst",
20 | "till",
21 | "glacial outwash",
22 | "quaternary sediment",
23 | "quartz vug",
24 | "calcite vug",
25 | "stromatolite",
26 | "cars honking at roadcut"
27 | )
28 |
--------------------------------------------------------------------------------
/inst/topics/july4th.R:
--------------------------------------------------------------------------------
1 | ## Aim : bingo card proposal for July 4th
2 | ## Author : Gabrielle Weinrott
3 |
4 | c(
5 | "Barbecue",
6 | "Neighborhood",
7 | "America",
8 | "Declaration of Independence",
9 | "Fireworks",
10 | "Parade",
11 | "Red, white and blue",
12 | "Sunburn",
13 | "USA",
14 | "Water balloons",
15 | "Swimming",
16 | "Nation",
17 | "July 4th",
18 | "Day off",
19 | "crackle",
20 | "Banners",
21 | "Anthem",
22 | "Camping",
23 | "Stars",
24 | "Stripes",
25 | "Liberty",
26 | "Flag",
27 | "Patriot",
28 | "Summer",
29 | "County fairground",
30 | "Lemonade"
31 | )
32 |
--------------------------------------------------------------------------------
/R/launch.R:
--------------------------------------------------------------------------------
1 | #' Launch the Shiny app that generates bingo cards
2 | #' @export
3 | launch <- function() {
4 | if (!requireNamespace("shiny", quietly = TRUE)) {
5 | stop("Install 'shiny' via 'install.packages(\"shiny\")' to run this function.",
6 | call. = FALSE)
7 | }
8 | if (!requireNamespace("shinyjs", quietly = TRUE)) {
9 | stop("Install 'shinyjs' via 'install.packages(\"shinyjs\")' to run this function.",
10 | call. = FALSE)
11 | }
12 | shiny::runApp(system.file("shiny", package = "bingo"),
13 | display.mode = "normal",
14 | launch.browser = TRUE)
15 | }
16 |
--------------------------------------------------------------------------------
/inst/topics/Bingo_Flowers.R:
--------------------------------------------------------------------------------
1 | ## Aim : bingo card proposal for flowers
2 | ## Author : Brittany Lopez Barreto
3 | c(
4 | "Lily",
5 | "Rose",
6 | "Carnation",
7 | "Baby's Breath",
8 | "Orchid",
9 | "Marigold",
10 | "Sunflower",
11 | "Hydrangea",
12 | "Tulip",
13 | "Peony",
14 | "Daisy",
15 | "Alstromeria",
16 | "Lavender",
17 | "Hibiscus",
18 | "Birds of Paradise",
19 | "Moonflower",
20 | "Pansy",
21 | "Hyacinth",
22 | "Petunia",
23 | "Poppy",
24 | "Snapdragon",
25 | "Violet",
26 | "Cosmos",
27 | "Calendula",
28 | "Azalea",
29 | "Begonia"
30 | )
31 |
--------------------------------------------------------------------------------
/inst/topics/game-of-thrones.R:
--------------------------------------------------------------------------------
1 | # creating Game of Thrones theme of events
2 |
3 | c(
4 | "Winter is Coming",
5 | "Cersei smirks as she talks",
6 | "Arya assassinates",
7 | "Dire Wolf",
8 | "The Hound vs. Clegane",
9 | "M' Lady",
10 | "Tyrion drinks wine",
11 | "Ravens",
12 | "Nightwatch",
13 | "Dragon(s) burn army",
14 | "Ice Dragon",
15 | "Needle",
16 | "Melisandre sees the Lord of Light",
17 | "Kingslayer",
18 | "Soldier(s) freezes",
19 | "Wights",
20 | "Free Folk",
21 | "Night King",
22 | "Wildlings",
23 | "The Wall",
24 | "King of the North",
25 | "Unsully",
26 | "Theon Greyjoy has PTSD attack",
27 | "Dragons fight each other"
28 | )
29 |
--------------------------------------------------------------------------------
/inst/topics/iowa.R:
--------------------------------------------------------------------------------
1 | # Iowa related things
2 | c("corn",
3 | "grinnell",
4 | "raygun",
5 | "I-80",
6 | "state fair",
7 | "Traveler's umbrella",
8 | "American Gothic",
9 | "Is this heaven?",
10 | "Zombie Burger",
11 | "Local foods",
12 | "Schnitzelbank",
13 | "RAGBRAI",
14 | "Jordan Creek Mall",
15 | "Hy-Vee",
16 | "Hawkeyes",
17 | "Cyclones",
18 | "Go West",
19 | "Clear Lake",
20 | "75% vowels, 100% Awesome",
21 | "Idiots out...",
22 | "John Deere",
23 | "John Wayne",
24 | "Hawkeye vodka",
25 | "Toppling Goliath",
26 | "Dari Barn",
27 | "Dairy Zone",
28 | "Surf Ballroom",
29 | "Saint's Rest",
30 | "The Musicman",
31 | "Iowa's best burger"
32 | )
33 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: bingo
2 | Title: Generate Bingo Cards
3 | Version: 0.0.0.9007
4 | Authors@R: c(
5 | person("Jennifer", "Bryan", , "jenny@stat.ubc.ca", c("cre", "aut")),
6 | person("Dean", "Attali", , "daattali@gmail.com", "aut")
7 | )
8 | Description: Generate bingo cards for fun and profit. Comes with built-in
9 | bingo squares for SuperBowl 50 and 'open' data / spreadsheet hell. You
10 | can also provide your own squares. Comes with a Shiny app.
11 | License: MIT + file LICENSE
12 | Depends:
13 | R (>= 3.2.1)
14 | Imports:
15 | grDevices,
16 | grid,
17 | utils
18 | Suggests:
19 | covr,
20 | shiny,
21 | shinyjs,
22 | testthat
23 | Encoding: UTF-8
24 | LazyData: true
25 | RoxygenNote: 6.1.1
26 |
--------------------------------------------------------------------------------
/inst/topics/dorm-room.R:
--------------------------------------------------------------------------------
1 | ## inspired by https://staff.tumblr.com/post/150094456055/dorm-room-bingo
2 | # issue 58
3 |
4 | c("chat noir poster",
5 | "mint edition infinite jest",
6 | "dvds",
7 | "terrible hamper",
8 | "plug-in air freshener",
9 | "doomed printer",
10 | "fear & loathing poster",
11 | "christmas lights (the bad kind)",
12 | "soil",
13 | "framed quote",
14 | "klimt",
15 | "decorative wall initial",
16 | "this basket",
17 | "christmas lights (the cute kind)",
18 | "vornado",
19 | "awful lamp",
20 | "eternal sunshine poster",
21 | "bag",
22 | "dusty old tea",
23 | "power strip",
24 | "t-shirt from a bank",
25 | "well-meaning bottle",
26 | "lotion",
27 | "plastic hangers",
28 | "headphones")
29 |
--------------------------------------------------------------------------------
/inst/topics/WeeklyJump.R:
--------------------------------------------------------------------------------
1 | # Japanese Mange in Weekly Syonen Jump
2 | # Authors (Toshiyuki Bandai):
3 |
4 | c(
5 | "Black Clover",
6 | "My Hero Academia",
7 | "Haikyu!!",
8 | "Food Wars!: Shokugeki no Soma",
9 | "Dr. Stone",
10 | "One Piece",
11 | "Dragon Ball",
12 | "Hikaru no Go",
13 | "Bleach",
14 | "Yu-Gi-Oh!",
15 | "Buso Renkin",
16 | "Assassination Classroom",
17 | "Death Note",
18 | "Rurouni Kenshin",
19 | "Psyren",
20 | "Nisekoi",
21 | "D.Grey-man",
22 | "Kuroko's Basketball",
23 | "The Prince of Tennis",
24 | "Toriko",
25 | "Dr. Slump",
26 | "Black Cat",
27 | "Bakuman",
28 | "Naruto",
29 | "Rokudenashi Blues",
30 | "Yu Yu Hakusho",
31 | "Hunter x Hunter",
32 | "Fist of the North Star",
33 | "Captain Tsubasa",
34 | "JoJo's Bizarre Adventure",
35 | "Slam Dunk"
36 | )
37 |
--------------------------------------------------------------------------------
/inst/topics/math-proofs.R:
--------------------------------------------------------------------------------
1 | # Common phrases and notation (good or bad) in math proofs
2 | # Submitted by Stephanie Reinders
3 | c("Let ... ",
4 | "Let epsilon be given",
5 | "Greek letters",
6 | "For each",
7 | "For all",
8 | "There exists",
9 | "Clearly",
10 | "Obviously",
11 | "Therefore",
12 | "Moreover",
13 | "Hence",
14 | "Thus",
15 | "So",
16 | "QED",
17 | "w.l.o.g.",
18 | "w.r.t.",
19 | "proof without words",
20 | "variables with subscripts",
21 | "variables with subscripts with subscripts",
22 | "variables with subscripts, superscripts, and hats",
23 | "e used as a variable",
24 | "necessary and sufficient",
25 | "Theorem",
26 | "Corollary",
27 | "by definition",
28 | "proof by induction",
29 | "proof by contrapositive",
30 | "proof by contradiction"
31 | )
32 |
--------------------------------------------------------------------------------
/inst/topics/boring-meeting.R:
--------------------------------------------------------------------------------
1 | # "Boring meeting" work bank - from http://bingo.saksena.net/bingo
2 |
3 | c(
4 | "low-risk",
5 | "client",
6 | "best practice",
7 | "initiative",
8 | "vision",
9 | "task force",
10 | "alternative",
11 | "market",
12 | "schedule",
13 | "milestone",
14 | "performance",
15 | "brainstorm",
16 | "scalable",
17 | "synergy",
18 | "action item",
19 | "passdown",
20 | "back-end",
21 | "braindump",
22 | "cross-platform",
23 | "customer",
24 | "deliver",
25 | "eyeballs",
26 | "revenue",
27 | "money",
28 | "incentive",
29 | "leverage",
30 | "value-add",
31 | "PUMA (please use more acronyms)",
32 | "committee",
33 | "mute the call",
34 | "forgot to mute the call",
35 | "at the table",
36 | "guru",
37 | "unicorn",
38 | "transformative"
39 | )
40 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | We happily accept contributions to our collection of bingo cards! If you'd like to add a card, simply submit a [pull request](https://help.github.com/articles/using-pull-requests) following these guidelines:
2 | - Create an R file under the [`inst/topics/`](./inst/topics/) directory
3 | - The name of the R file will be used as the name of the topic of bingo cards
4 | - The file should return a character vector containing the words or phrases to put in the squares
5 | - There should be at least 24 squares, in order to make 5 x 5 bingo cards
6 | - Optional: at the top of the file, add your name and a short description of the card as a comment
7 | - You can look at the [existing examples](./inst/topics/)
8 |
9 | We'll try to be as responsive as possible in reviewing and accepting pull requests. We appreciate your contributions!
10 |
--------------------------------------------------------------------------------
/inst/topics/csama.R:
--------------------------------------------------------------------------------
1 | # Things you expect to encounter in CSAMA course
2 | # http://www.huber.embl.de/csama2016/
3 | # Contributed by CSAMA 2016 students after successful Git/GitHub lab :)
4 | # Authors (GitHub handles):
5 | # nkurzawa, KaBach
6 | c(
7 | "edgeR vs. DEseq2",
8 | "Hadley Wickham",
9 | "Portugal vs. France",
10 | "Hypothesis Testing",
11 | "Mountainbiking",
12 | "Twitter",
13 | "RStudio",
14 | "Julia",
15 | "Bioconductor",
16 | "Differential Expression",
17 | "GitHub",
18 | "data.frame",
19 | "git vs. svn",
20 | "data_frame",
21 | "tibble",
22 | "dplyr",
23 | "pirates vs. ninjas",
24 | "vignette",
25 | "vino",
26 | "espresso",
27 | "Pizza",
28 | "sun burn",
29 | "sun creme",
30 | "Jenny Bryan",
31 | "commit",
32 | "push",
33 | "pull",
34 | "add",
35 | "stage",
36 | "I haven't installed all necessary packages",
37 | "charging device"
38 | )
39 |
--------------------------------------------------------------------------------
/man/plot.bingo.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/bingo.R
3 | \name{plot.bingo}
4 | \alias{plot.bingo}
5 | \title{Plot bingo cards}
6 | \usage{
7 | \method{plot}{bingo}(x, dir = ".", fontsize = 14,
8 | pdf_base = "bingo-", ...)
9 | }
10 | \arguments{
11 | \item{x}{a \code{\link{bingo}} object containing one or more bingo cards}
12 |
13 | \item{dir}{directory where you want to write files}
14 |
15 | \item{fontsize}{size of bingo square font}
16 |
17 | \item{pdf_base}{base of the sequential filenames for the printable bingo card
18 | files}
19 |
20 | \item{...}{not used}
21 | }
22 | \value{
23 | Vector containing the filenames of all the generated cards
24 | (invisibly)
25 | }
26 | \description{
27 | Plot bingo cards
28 | }
29 | \note{
30 | Does not actually plot the cards to the graphics device
31 | }
32 | \examples{
33 | bc <- bingo()
34 | plot(bc)
35 | }
36 |
--------------------------------------------------------------------------------
/R/utils.R:
--------------------------------------------------------------------------------
1 | vet_squares <- function(words) {
2 | if (!inherits(words, "character")) words <- as.character(words)
3 | words <- unique(words)
4 | words
5 | }
6 |
7 | wrap_one <- function(x, w = 13) {
8 | stopifnot(length(x) == 1L)
9 | paste(strwrap(x, width = w), collapse = "\n")
10 | }
11 | wrap_it <- Vectorize(wrap_one, "x", USE.NAMES = FALSE)
12 |
13 | make_grid <- function(n) {
14 | gridlines <- grid::unit( (0:n) / n, "npc")
15 | grid::grid.grill(h = gridlines, v = gridlines) # gp = gpar(col="grey"))
16 | gridlines
17 | }
18 |
19 | ## write something to compute n from a vector or matrix of bingo card data
20 | infer_n <- function(bc) {
21 | m <- if (length(dim(bc) == 2)) nrow(bc) else length(bc)
22 | n_ok <- 3:6
23 | n_sq <- n_ok ^ 2
24 | n <- n_ok[match(m, n_sq)]
25 | if (is.na(n))
26 | stop("Sorry, we are only prepared to plot square bingo cards ",
27 | "with ", min(n_ok), " to ", max(n_ok), " rows/cols.", call. = FALSE)
28 | n
29 | }
30 |
--------------------------------------------------------------------------------
/inst/topics/open-data.R:
--------------------------------------------------------------------------------
1 | #' The agony of other people's data.
2 |
3 | c(
4 | "duplicate rows",
5 | "website maze",
6 | "session has timed out",
7 | "broken formula",
8 | "mystery column",
9 | "metadata mixed with data",
10 | "out of date docs",
11 | ".XLSB",
12 | "assumed knowledge",
13 | "non-standard country names",
14 | "blank rows",
15 | "hidden cells",
16 | "circular references",
17 | "split cells",
18 | "long fieldnames are long",
19 | "metadata at end of spreadsheet",
20 | "arcane codes",
21 | "please enable macros",
22 | "colour as data",
23 | "merged cells",
24 | "acronym WTF?",
25 | "starred numbers*",
26 | "PDF tables",
27 | "numbers formatted as text",
28 | "metadata expressed as fieldnames",
29 | "fieldname EDA",
30 | "regex-driven workflow",
31 | "named region non-sequiturs",
32 | "dates formatted as numbers",
33 | "ununiform date format",
34 | "scanned tables",
35 | "password-protected files",
36 | "screenshot of report"
37 | )
38 |
--------------------------------------------------------------------------------
/inst/topics/news-nerd.R:
--------------------------------------------------------------------------------
1 | ### inspired by https://twitter.com/bizweekgraphics/status/1116385470534045696/photo/1
2 | ### address issue #56
3 |
4 | c("has spoken at NICAR for the last 3 years",
5 | "RTs any map with hillshades",
6 | "worships Amanda Cox",
7 | "d3 v4 4ever",
8 | "some personal news",
9 | "googling flexbox",
10 | "srccon community call",
11 | "relies on a guy named kyng chaos",
12 | "Census update dates in calendar",
13 | "very strong opinions about the Data Visualization Society",
14 | "\"we are not a service desk\"",
15 | "Havre de Grace",
16 | "writes?",
17 | "has googled \"how to center div\" 300 times",
18 | "has had canvas on resume for three years but never used it",
19 | "blocked by edward tufte",
20 | "Knight Foundation fellowship",
21 | "loves observable",
22 | "has a tinyletter",
23 | "spend three weeks installing qgis",
24 | "forgot to test in IE",
25 | "tweets about cocktails",
26 | "snd bronze",
27 | "hates obervable",
28 | "newsnerdery"
29 | )
30 |
--------------------------------------------------------------------------------
/inst/topics/conference-call.R:
--------------------------------------------------------------------------------
1 | c("Can you see my screen?",
2 | "Can you hear me?",
3 | "Could everyone mute their phones?",
4 | "Someone forgets they are on mute",
5 | "I'm getting an echo",
6 | "Laggy screen",
7 | "Who just joined?",
8 | "Background noise",
9 | "Making a mistake in the dial-in code",
10 | "Someone in the room mutes to talk over the call",
11 | "Starting late",
12 | "Running over",
13 | "Small talk",
14 | "Someone randomly joins the wrong call",
15 | "People start talking at the same time",
16 | "Someone loses the connection and re-joins",
17 | "Hold music",
18 | "Bad signal",
19 | "Let's do a round of introductions",
20 | "Someone in a car",
21 | "Dog barking",
22 | "Crying baby",
23 | "Siren in the background",
24 | "Circle back on that",
25 | "Take this offline",
26 | "Hard stop",
27 | "Switching between calls",
28 | "Someone takes another call and forgets to mute",
29 | "Keyboard sounds",
30 | "Moves the microphone",
31 | "Someone is eating"
32 | )
33 |
--------------------------------------------------------------------------------
/inst/shiny/www/app.css:
--------------------------------------------------------------------------------
1 | @media print {
2 | .noprint {
3 | display: none;
4 | }
5 | }
6 |
7 | body > .container-fluid {
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
12 | body {
13 | padding-bottom: 20px;
14 | }
15 |
16 | #authors {
17 | margin-bottom: 15px;
18 | margin-top: -5px;
19 | font-style: italic;
20 | }
21 |
22 | #form {
23 | background: #f9f9f9;
24 | padding: 10px 20px 20px;
25 | border-bottom: 1px solid #aaa;
26 | font-size: 1.2em;
27 | }
28 |
29 | #apptitle {
30 | margin-top: 0;
31 | }
32 |
33 | #wordsinput {
34 | margin-top: -10px;
35 | }
36 |
37 | #wordsinput .form-group, #wordsinput .progress {
38 | margin-bottom: 0;
39 | }
40 |
41 | #error {
42 | margin-top: 10px;
43 | color: red;
44 | }
45 |
46 | table.bingo-card {
47 | border-collapse: collapse;
48 | table-layout: fixed;
49 | margin-top: 20px;
50 | margin-left: 20px;
51 | float: left;
52 | }
53 |
54 | .bingo-card td {
55 | border: 1px solid black;
56 | text-align: center;
57 | word-break: break-word;
58 | }
59 |
--------------------------------------------------------------------------------
/R/Eurovision_bingo.R:
--------------------------------------------------------------------------------
1 | #Eurovision Bingo (for usein the grand final, because certain cells pertain to voting results)
2 | c("Costume change/reveal",
3 | "Multilingual song",
4 | "Wink at camera",
5 | "Pyrotechnics",
6 | "Fog machine",
7 | "Background interpretive dancers",
8 | "Dramatic high note",
9 | "Sparkle/sequin outfit",
10 | "Crazy hair/hat",
11 | "Voice crack",
12 | "Dance break",
13 | "Song not in English",
14 | "Hair flip",
15 | "Awkward green room interview",
16 | "Hosts are cringy",
17 | "Seizure inducing lights",
18 | "Wind machine",
19 | "Dramatic solo ballad",
20 | "Dizzying LED backdrop",
21 | "Someone cries",
22 | "Shirtless male dancers",
23 | "Song has vague uplifting message",
24 | "Flag waved at camera",
25 | "Leather pants",
26 | "Synchronized dance routine",
27 | "Country outside of Europe performs",
28 | "Previous contestant makes an apperance",
29 | "Obviously fake instruments on stage",
30 | "Clapping during a song",
31 | "Love song",
32 | "Technical difficulties",
33 | "'Heart hands' to the camera",
34 | "Huge props")
35 |
--------------------------------------------------------------------------------
/inst/topics/manuscript-review.R:
--------------------------------------------------------------------------------
1 | # Common issues in manuscript reviews
2 | # Submitted by Haley Hedlin
3 | c("No limitations described",
4 | "Figure legends missing",
5 | "Statistical software not specified",
6 | "Acronym not defined",
7 | "Not clear what test used to calculate a result",
8 | "Table/figure not mentioned in results",
9 | "Parameterization of statistical model not clear",
10 | "CONSORT diagram missing",
11 | "Inclusion/exclusion criteria unclear",
12 | "Not clear whether analyses chosen a priori",
13 | "Handling of missing data not described",
14 | "No confidence intervals provided",
15 | "Not clear if model assumptions were checked",
16 | "Bad graphs (eg pie charts, 3d bar charts)",
17 | "Hypotheses not clear",
18 | "Level of significance reported",
19 | "Unclear statistical methods",
20 | "Unclear or missing baseline characteristics/Table 1",
21 | "Improper use of statistical terms",
22 | "Not clear if significant results are clinically or statistically significant",
23 | "Measured values expressed to the appropriate precision",
24 | "R packages not cited",
25 | "Need to cite more papers by [me]",
26 | "Unclear significance of work"
27 | )
28 |
--------------------------------------------------------------------------------
/inst/topics/stat-ecology.R:
--------------------------------------------------------------------------------
1 | # Statistical ecology themed bingo
2 | c("population dynamics",
3 | "life history",
4 | "state-space model",
5 | "Bayesian",
6 | "Poisson",
7 | "binomial",
8 | "species",
9 | "R (software)",
10 | "collaboration",
11 | "environmental drivers",
12 | "animal behavior",
13 | "genetic diversity",
14 | "operational taxonomic unit",
15 | "keystone species",
16 | "reproductive success",
17 | "model selection",
18 | "survival probability",
19 | "life stage",
20 | "density dependence",
21 | "reproducible research",
22 | "regression",
23 | "R-squared",
24 | "mixed effects",
25 | "manuscript",
26 | "noisy data",
27 | "hierarchical model",
28 | "conference",
29 | "sample design",
30 | "p-value problem",
31 | "statistical significance",
32 | "statistical significance vs. scientific significance",
33 | "confidence interval",
34 | "beta regression on proportions",
35 | "ecological network",
36 | "bipartite network",
37 | "interaction network",
38 | "Lotka-Volterra equations",
39 | "exponential growth",
40 | "generalized linear model",
41 | "logistic regression",
42 | "heteroscedastic",
43 | "ordination",
44 | "community detection"
45 | )
46 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | # DO NOT CHANGE the "init" and "install" sections below
2 |
3 | # Download script file from GitHub
4 | init:
5 | ps: |
6 | $ErrorActionPreference = "Stop"
7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
8 | Import-Module '..\appveyor-tool.ps1'
9 |
10 | install:
11 | ps: Bootstrap
12 |
13 | cache:
14 | - C:\RLibrary
15 |
16 | environment:
17 | NOT_CRAN: true
18 | # env vars that may need to be set, at least temporarily, from time to time
19 | # see https://github.com/krlmlr/r-appveyor#readme for details
20 | USE_RTOOLS: true
21 | # R_REMOTES_STANDALONE: true
22 |
23 | # Adapt as necessary starting from here
24 |
25 | build_script:
26 | - travis-tool.sh install_deps
27 |
28 | test_script:
29 | - travis-tool.sh run_tests
30 |
31 | on_failure:
32 | - 7z a failure.zip *.Rcheck\*
33 | - appveyor PushArtifact failure.zip
34 |
35 | artifacts:
36 | - path: '*.Rcheck\**\*.log'
37 | name: Logs
38 |
39 | - path: '*.Rcheck\**\*.out'
40 | name: Logs
41 |
42 | - path: '*.Rcheck\**\*.fail'
43 | name: Logs
44 |
45 | - path: '*.Rcheck\**\*.Rout'
46 | name: Logs
47 |
48 | - path: '\*_*.tar.gz'
49 | name: Bits
50 |
51 | - path: '\*_*.zip'
52 | name: Bits
53 |
--------------------------------------------------------------------------------
/R/topics.R:
--------------------------------------------------------------------------------
1 | # Environment containing all the word lists of all topics
2 | topics <- new.env(parent = emptyenv())
3 |
4 | #' Get all bingo card topics
5 | #'
6 | #' @return A character vector containing the names of all the bingo card topics
7 | #' @export
8 | #'
9 | #' @examples
10 | #' get_topics()
11 | get_topics <- function() {
12 | ls(topics)
13 | }
14 |
15 | #' Get the words of a bingo card topic
16 | #'
17 | #' @param topic Name of a topic (a string)
18 | #'
19 | #' @return A character vector containing all the possible words of a bingo card
20 | #' topic
21 | #' @export
22 | #'
23 | #' @examples
24 | #' get_topic("open-data")
25 | get_topic <- function(topic) {
26 | if (!topic %in% get_topics()) {
27 | stop("Topic '", topic, "' does not exist", call. = FALSE)
28 | }
29 | topics[[topic]]
30 | }
31 |
32 | # When the package loads, load all the topics words
33 | .onLoad <- function(libname, pkgname) {
34 | rm(list = ls(topics), envir = topics)
35 | topics_dir <- system.file("topics", package = "bingo")
36 | all_topics <- list.files(topics_dir, full.names = FALSE, pattern = "\\.R$")
37 | all_topics <- sub("\\.R$", "", all_topics)
38 |
39 | lapply(all_topics, function(x) {
40 | tryCatch({
41 | topic_file <- file.path(topics_dir, paste0(x, ".R"))
42 | words <- source(topic_file)$value
43 | assign(x, words, topics)
44 | }, error = function(err) {
45 | warning("Topic '", x, "' is mal-formed", call. = FALSE)
46 | })
47 | })
48 | }
49 |
--------------------------------------------------------------------------------
/inst/topics/bad-data.R:
--------------------------------------------------------------------------------
1 | # Inspired by the \href{https://github.com/Quartz/bad-data-guide}{Quartz Guide
2 | # to Bad Data}. Identifies bad data smells that should make you extremely
3 | # vigilant in your cleaning and sanity checks.
4 | c(
5 | "Blank/null values aren't explained",
6 | "Data that \"must exist\" does not, in fact, exist",
7 | "Data that \"cannot exist\" does, in fact, exist",
8 | "Duplicate rows",
9 | "Metric? Imperial? Ask the dust ...",
10 | "65,535 or 2,147,483,647 or 4,294,967,295",
11 | "555-3485 or 867-5309",
12 | "1970-01-01\nT00:00:00Z or 1969-12-31\nT23:59:59Z",
13 | "January 1st, 1900 or January 1st, 1904",
14 | "Data is \"helpfully\" pre-aggregated",
15 | "Aggregates and computed totals don't match",
16 | "Line ending chaos ... \\n vs \\r\\n vs \\r",
17 | "Yo, I hear you like metadata mixed with your data",
18 | "Spreadsheet has exactly 65,536 rows",
19 | "Missing data that passes for real data, eg 0 or 99",
20 | "Leading zeroes stripped to convert text to numbers",
21 | "Inexplicable outliers",
22 | ## this does not work well with grid and PDF
23 | ## http://stackoverflow.com/questions/28746938/ggsave-losing-unicode-charaters-from-ggplotgridextra
24 | #"\uFFFD\uFFFD\uFFFD Mojibake \uFFFD\uFFFD\uFFFD",
25 | "Garbled text suggests encoding problems",
26 | "Data disguised as formatting",
27 | "Ambiguous American date formats, eg 03/04/16",
28 | "\"Virgin Birth\", ie no provenance",
29 | "Location of 0\u00B0N 0\u00B0E, ie \"Null Island\"",
30 | "Spelling mistakes that reek of hand-typed data",
31 | "US zip codes 12345 or 90210",
32 | "There's no unique identifier",
33 | "Password-protected data"
34 | )
35 |
--------------------------------------------------------------------------------
/inst/shiny/global.R:
--------------------------------------------------------------------------------
1 | # Given a string with comma-separated phrases, extract the phrases
2 | getWordsText <- function(text) {
3 | trimws(strsplit(text, ",")[[1]])
4 | }
5 |
6 | # Given a file with comma-separated or newline-separated phrases,
7 | # extract the phrases
8 | getWordsFile <- function(file) {
9 | getWordsText(paste(readLines(file), collapse = ","))
10 | }
11 |
12 |
13 | # Make sure there are enough phrases to fill at least one card
14 | validateSize <- function(words, size) {
15 | if (length(words) < (size * size - 1)) {
16 | stop(sprintf("You need at least %s phrases to fill a %sx%s bingo card (you provided %s)",
17 | size * size - 1, size, size, length(words)))
18 | }
19 | }
20 |
21 | # Create CSS that is needed to customize the appearance of the bingo cards
22 | generateCardCSS <- function(length = 10, textSize = 16) {
23 | tags$style(paste0(
24 | "table.bingo-card {",
25 | " width: ", length, "cm;",
26 | " height: ", length, "cm;",
27 | " font-size: ", textSize, "px;",
28 | "}"
29 | ))
30 | }
31 |
32 | # Generate HTML for a bingo card
33 | generateCard <- function(words = LETTERS, size = 5) {
34 | # Randomly select phrases and insert "FREE" in the middle
35 | words <- sample(words, size * size - 1)
36 | middle <- size * size / 2 + 1
37 | middleWord <- words[middle]
38 | words[middle] <- "FREE"
39 | words[length(words) + 1] <- middleWord
40 | # Just for convenience, make the phrases a 2D matrix instead of 1D vector
41 | dim(words) <- c(size, size)
42 |
43 | tags$table(
44 | class = "bingo-card",
45 | tags$tbody(
46 | lapply(seq(size), function(row) {
47 | tags$tr(
48 | lapply(seq(size), function(col) {
49 | tags$td(words[row, col])
50 | })
51 | )
52 | })
53 | )
54 | )
55 | }
56 |
--------------------------------------------------------------------------------
/inst/topics/useR-conf.R:
--------------------------------------------------------------------------------
1 | # Things you expect to encounter in useR conference
2 | # Authors (GitHub handles):
3 | # bearloga, corynissen, rmflight, Luke4130, barryrowlingson, hrbrmstr, spholmes,
4 | # trestletech, daroczig, kylehamilton, petestmarie, yanlesin
5 | c(
6 | "R vs. Python",
7 | "hadleyverse",
8 | "pipe",
9 | "A slide with a cat on it",
10 | "rmarkdown",
11 | "shiny",
12 | "bookdown",
13 | "grammar of",
14 | "R inferno",
15 | "%>%",
16 | "CRANdalf",
17 | "RConsortium",
18 | "mtcars",
19 | "diamonds",
20 | "Hadleyverse",
21 | "ArrCeePeePee",
22 | "cats",
23 | "kittens",
24 | "StackOverflow",
25 | "Data Science",
26 | "rainbow",
27 | "pie chart",
28 | "SAS",
29 | "SPSS",
30 | "Excel",
31 | "R4",
32 | "R5",
33 | "R6",
34 | "Splus",
35 | "Tibco",
36 | "R-forge",
37 | "library!=package",
38 | "%<>%",
39 | "sell out",
40 | "cloud",
41 | "language war",
42 | "Julia",
43 | "R-bloggers",
44 | "analytics",
45 | "docker",
46 | "A failed live demo",
47 | "two people exchanging business cards",
48 | "in the cloud",
49 | "AWS",
50 | "A laptop with > 5 R themed stickers",
51 | "A t-shirt from a past R conference",
52 | "Microsoft Windows running on a PC",
53 | "Somebody coding in emacs / vi",
54 | "spark / sparkr",
55 | "notebook",
56 | "repo",
57 | "base (as in base vs ggplot2)",
58 | "virtually every dplyr verb",
59 | "literate",
60 | "sankey",
61 | "contour",
62 | "flowchart",
63 | "reproducible",
64 | "interactive",
65 | "stata",
66 | "structural equation",
67 | "credible",
68 | "big data",
69 | "subversion",
70 | "cloud scale",
71 | "Beamer slides",
72 | "GitHub",
73 | "CRAN",
74 | "install",
75 | "development",
76 | "version",
77 | "bug(fix)",
78 | "devtools",
79 | "roxygen",
80 | "Rcpp",
81 | "benchmark",
82 | "profiling",
83 | "is that Hadley Wickham?",
84 | "Bayesian"
85 | )
86 |
--------------------------------------------------------------------------------
/inst/topics/olympic-sports.R:
--------------------------------------------------------------------------------
1 | # "olympic sports" past and present word bank - source https://en.wikipedia.org/wiki/Olympic_sports
2 |
3 | c(
4 | "Diving",
5 | "Marathon swimming",
6 | "Swimming",
7 | "Synchronized swimming",
8 | "Water polo",
9 | "3-on-3 basketball",
10 | "Basketball",
11 | "Canoe/kayak (sprint)",
12 | "Canoe/kayak (slalom)",
13 | "BMX freestyle",
14 | "BMX racing",
15 | "Mountain biking",
16 | "Road cycling",
17 | "Track cycling",
18 | "Gymnanastics - Artistic",
19 | "Gymnanastics - Rhythmic",
20 | "Gymnanastics - Trampoline",
21 | "Volleyball (beach)",
22 | "Volleyball (indoor)",
23 | "Equestrian / Dressage",
24 | "Equestrian / Eventing",
25 | "Equestrian / Jumping",
26 | "Freestyle wrestling",
27 | "Greco-Roman wrestling",
28 | "Archery",
29 | "Athletics",
30 | "Badminton",
31 | "Baseball",
32 | "Boxing",
33 | "Fencing",
34 | "Field hockey",
35 | "Football",
36 | "Golf",
37 | "Handball",
38 | "Judo",
39 | "Karate",
40 | "Modern pentathlon",
41 | "Rowing",
42 | "Rugby sevens",
43 | "Sailing",
44 | "Shooting",
45 | "Skateboarding",
46 | "Softball",
47 | "Sport climbing",
48 | "Surfing",
49 | "Table tennis",
50 | "Taekwondo",
51 | "Tennis",
52 | "Triathlon",
53 | "Weightlifting",
54 | "Equestrian / Vaulting",
55 | "Handball / Field Handball",
56 | "Rugby / Rugby union",
57 | "Basque pelota",
58 | "Cricket",
59 | "Croquet",
60 | "Lacrosse",
61 | "Jeu de paume",
62 | "Polo",
63 | "Rackets",
64 | "Roque",
65 | "Tug of war",
66 | "Water motorsports",
67 | "Figure skating",
68 | "Ice hockey",
69 | "Figure skating",
70 | "Speed skating",
71 | "Short track speed skating",
72 | "Curling",
73 | "Cross-country skiing",
74 | "Alpine skiing",
75 | "Ski jumping",
76 | "Nordic combined",
77 | "Freestyle skiing",
78 | "Snowboarding",
79 | "Biathlon",
80 | "Luge",
81 | "Bobsleigh",
82 | "Skeleton",
83 | "Biathlon / Military Patrol"
84 | )
85 |
--------------------------------------------------------------------------------
/R/bingo.R:
--------------------------------------------------------------------------------
1 | #' Generate bingo cards
2 | #'
3 | #' @param n_cards number of cards
4 | #' @param words text for the bingo squares
5 | #' @param n number of rows/columns for one card
6 | #'
7 | #' @return a \code{bingo} object, which is really just a character matrix
8 | #' @export
9 | #'
10 | #' @examples
11 | #' bingo()
12 | bingo <- function(n_cards = 1, words, n = 5) {
13 | stopifnot(n %% 2 == 1)
14 |
15 | if (missing(words)) {
16 | words <- topics[['open-data']]
17 | }
18 |
19 | words <- vet_squares(words)
20 | m <- length(words)
21 | n_sq <- (n ^ 2) - 1
22 | stopifnot(m >= n_sq)
23 |
24 | cards <- replicate(n_cards, words[sample.int(m, size = n_sq)])
25 | up_to <- trunc(n_sq/2)
26 | cards <- rbind(utils::head(cards, up_to),
27 | rep("FREE", n_cards),
28 | utils::tail(cards, up_to))
29 | row.names(cards) <- NULL
30 | structure(cards, class = c("bingo", "matrix"))
31 | }
32 |
33 | #' Plot bingo cards
34 | #'
35 | #' @param x a \code{\link{bingo}} object containing one or more bingo cards
36 | #' @param dir directory where you want to write files
37 | #' @param fontsize size of bingo square font
38 | #' @param pdf_base base of the sequential filenames for the printable bingo card
39 | #' files
40 | #' @param ... not used
41 | #'
42 | #' @export
43 | #' @note Does not actually plot the cards to the graphics device
44 | #' @return Vector containing the filenames of all the generated cards
45 | #' (invisibly)
46 | #' @examples
47 | #' bc <- bingo()
48 | #' plot(bc)
49 | plot.bingo <- function(x, dir = ".", fontsize = 14, pdf_base = "bingo-", ...) {
50 | bc <- x
51 | n <- infer_n(bc)
52 | n_cards <- ncol(bc)
53 | bc_wrapped <- apply(bc, 2, wrap_it)
54 | message("Writing to file ...")
55 | filenames <- c()
56 | for (i in seq_len(n_cards)) {
57 | fname <- file.path(dir, paste0(pdf_base, sprintf("%02d", i), ".pdf"))
58 | message(" ", fname)
59 | filenames <- c(filenames, fname)
60 | grDevices::pdf(fname, width = 7, height = 7)
61 | plot_one(bc_wrapped[ , i], n = n, fontsize = fontsize)
62 | grDevices::dev.off()
63 | }
64 | invisible(filenames)
65 | }
66 |
67 | plot_one <- function(x, n, fontsize = 14) {
68 | grid::grid.newpage()
69 | g <- make_grid(n)
70 | centers <- g[-1] - grid::unit(1/(n * 2),"npc")
71 | grid::grid.text(label = x, x = rep(centers, each = n), y = centers,
72 | gp = grid::gpar(fontsize = fontsize))
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/inst/shiny/server.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 | library(shinyjs)
3 |
4 | source("global.R")
5 |
6 | function(input, output, session) {
7 |
8 | values <- reactiveValues(cardsHTML = NULL)
9 |
10 | # show/hide the advanced options
11 | observeEvent(input$advancedBtn, {
12 | toggle("advanced", anim = TRUE)
13 | })
14 |
15 | # show an error message when an error occurs
16 | observeEvent(values$error, {
17 | html("errormsg", values$error)
18 | show("error", anim = TRUE)
19 | })
20 |
21 | # disable the Generate button when no words are entered
22 | observe({
23 | submitEnabled <- TRUE
24 | if ( (input$uploadType == "box" && !nzchar(input$wordsBox)) ||
25 | (input$uploadType == "file" && is.null(input$wordsFile))
26 | ) {
27 | submitEnabled <- FALSE
28 | }
29 | toggleState("generatePdf", condition = submitEnabled)
30 | toggleState("generateHtml", condition = submitEnabled)
31 | })
32 |
33 | # Generate PDF cards
34 | output$generatePdf <- downloadHandler(
35 | filename = function() {
36 | "bingo-cards.zip"
37 | },
38 | content = function(file) {
39 | tryCatch({
40 | # make sure there are enough phrases to fill at least one card
41 | size <- as.integer(input$size)
42 | validateSize(words(), size)
43 |
44 | # generate the cards
45 | cards <- bingo::bingo(n_cards = input$numberToMake, words = words(), n = size)
46 | filenames <- plot(cards, dir = tempdir(), fontsize = input$textSize)
47 | wd <- setwd(dirname(filenames[1]))
48 | zip(file, basename(filenames))
49 | setwd(wd)
50 | },
51 | error = function(err) {
52 | stop(err$message)
53 | })
54 | }
55 | )
56 |
57 | words <- reactive({
58 | if (input$uploadType == "box") {
59 | words <- getWordsText(input$wordsBox)
60 | } else if (input$uploadType == "file") {
61 | words <- getWordsFile(input$wordsFile$datapath)
62 | } else {
63 | words <- bingo::get_topic(input$uploadType)
64 | }
65 | })
66 |
67 | # Generate HTML cards
68 | observeEvent(input$generateHtml, {
69 | tryCatch({
70 | size <- as.integer(input$size)
71 | validateSize(words(), size)
72 |
73 | hide("error")
74 | show("print")
75 |
76 | # Joe Cheng won't like, but I have to use reactiveValues here
77 | values$cardsHTML <-
78 | tagList(
79 | generateCardCSS(input$length, input$textSize),
80 | lapply(seq(input$numberToMake), function(i) {
81 | generateCard(words(), size)
82 | })
83 | )
84 | },
85 | error = function(err) {
86 | values$error <- err$message
87 | })
88 | })
89 |
90 | # render the cards HTML when it changes
91 | output$cards <- renderUI({
92 | values$cardsHTML
93 | })
94 | }
95 |
--------------------------------------------------------------------------------
/inst/topics/football.R:
--------------------------------------------------------------------------------
1 | # Denver Broncos vs. Carolina Panthers
2 | c(
3 |
4 | ## gameplay, generic
5 | ## TO DO: move out to generic football
6 | "Quarterback run for 1st down or TD",
7 | "Missed field goal",
8 | "Dropped pass",
9 | "Fumble!",
10 | "Interception!",
11 | "Passing interference",
12 | "Challenge",
13 | "QB kneel or sneak",
14 | "Bootleg or reverse",
15 | "Special teams TD",
16 | "Team goes for it on 4th down",
17 | "Roughing the passer",
18 | "Pick Six",
19 | "Lineman gets to run with football",
20 | "Kick return of 35+ yards",
21 | "Player dives for pylon",
22 |
23 | ## gameplay, team or player specific
24 | "Someone besides Peyton or Cam passes",
25 | ## TO DO: these could be templated
26 | "Gain of 30+ yds for Broncos",
27 | "Gain of 30+ yds for Panthers",
28 | "Panthers passing touchdown",
29 | "Broncos passing touchdown",
30 | "Panthers rushing touchdown",
31 | "Broncos rushing touchdown",
32 | "Holding against the Broncos",
33 | "Holding against the Panthers",
34 | "Panthers field goal",
35 | "Broncos field goal",
36 | "Panthers call timeout",
37 | "Broncos call timeout",
38 |
39 | ## the game of football, generic
40 | "\"concussion protocol\"",
41 | "Fan holding sign with pun",
42 | "Coach removes headphones in anger/disgust",
43 | "Commentator calls someone \"great guy\"",
44 | "Shot of a celeb in crowd",
45 | "Gratuitous cheerleader close-up",
46 | "Shirtless fan with body paint",
47 | "Shot of team owner",
48 | "Lip-readable expletive from player or coach",
49 | "Over-the-top celebration from special teams",
50 | "Military flyover",
51 | "Shot of US soldiers watching from abroad",
52 | "Implication that God cares about football",
53 | "Player/coach slaps other player's butt",
54 | "Elaborate touchdown celebration",
55 | "Non-football player gets knocked down",
56 | "Either score or total score divisible by 11",
57 | "Animal playing cutely on field",
58 |
59 | ## specific to this game, non-gameplay
60 | "Shot or interview of Eli or Archie Manning",
61 | "Reference to Cam's off-field fashion",
62 | "Commentary on Peyton's alleged drug use",
63 | "Mention of Cam and BFF Stephen Curry",
64 | "Shot of Golden Gate Bridge",
65 | "\"Silicon Valley and tech\" blah blah blah",
66 | "Mike Carey is WRONG",
67 | "Unexpected artist joins Beyonc\u00E9",
68 | "Cam's Superman shirt-opening thing",
69 | "Idle speculation it's Peyton's last game"
70 | )
71 |
72 | ## lying around from past
73 | ## Troy Aikman says something inane
74 | ## NFL Labor dispute mentioned
75 | ## Aaron Rodgers Matador/put on the belt move
76 | ## Shot of a fan in a Cheesehead hat
77 | ## Rothlisberger avoids what looked like a sure sack
78 | ## Big Ben throws an interception
79 | ## Clay Mathews sacks Big Ben
80 | ## Reference to Clay Matthew's "football family"
81 |
--------------------------------------------------------------------------------
/inst/shiny/ui.R:
--------------------------------------------------------------------------------
1 | library(shiny)
2 |
3 | fluidPage(
4 | shinyjs::useShinyjs(),
5 | tags$head(
6 | tags$link(href = "app.css", rel = "stylesheet")
7 | ),
8 |
9 | div(
10 | class = "noprint",
11 | id = "form",
12 | h1(id = "apptitle", "Bingo card generator"),
13 | div(id = "authors",
14 | "By", a("Jenny Bryan", href = "https://twitter.com/jennybryan"),
15 | "and", a("Dean Attali", href = "http://deanattali.com"),
16 | HTML("•"),
17 | "Code", a("on GitHub", href = "https://github.com/jennybc/bingo")
18 | ),
19 | selectInput("cardType", NULL,
20 | c("Create HTML cards to print" = "html",
21 | "Create PDF cards to download" = "pdf")
22 | ),
23 | numericInput("numberToMake", "Number of cards to generate", 5, 1),
24 | selectInput("uploadType", "Phrases to use",
25 | c(bingo::get_topics(),
26 | "(Type phrases into a box)" = "box",
27 | "(Upload text file)" = "file")),
28 | div(
29 | id = "wordsinput",
30 | conditionalPanel(
31 | condition = "input.uploadType == 'box'",
32 |
33 | div(class = "form-group shiny-input-container",
34 | tags$textarea(id = "wordsBox", rows = 7, class = "form-control",
35 | paste(LETTERS, collapse = ","))
36 | ),
37 | helpText("Phrases must be separated by commas")
38 | ),
39 | conditionalPanel(
40 | condition = "input.uploadType == 'file'",
41 | fileInput("wordsFile", NULL),
42 | helpText("Phrases must be separated by commas")
43 | )
44 | ),
45 | actionLink("advancedBtn", "More options"), br(),
46 | shinyjs::hidden(
47 | div(
48 | id = "advanced",
49 | selectInput("size", "Number of cells", selected = "5",
50 | c("3x3" = "3", "5x5" = "5")),
51 | numericInput("textSize", "Text size (in pixels)", 14, 8),
52 | conditionalPanel(
53 | condition = "input.cardType == 'html'",
54 | numericInput("length", "Card size (in centimeters)", 20, 5)
55 | )
56 | )
57 | ),
58 | br(),
59 | conditionalPanel(
60 | condition = "input.cardType == 'pdf'",
61 | downloadButton('generatePdf', 'Download cards!', class = "btn-primary btn-lg")
62 | ),
63 | conditionalPanel(
64 | condition = "input.cardType == 'html'",
65 | actionButton("generateHtml", "Generate cards!", class = "btn-primary btn-lg"),
66 | shinyjs::hidden(
67 | actionButton("print", "Print these cards", icon("print"),
68 | onclick = "javascript:window.print()", class = "btn-lg")
69 | )
70 | ),
71 | br(),
72 | conditionalPanel(
73 | condition = "input.cardType == 'html'",
74 | shinyjs::hidden(
75 | div(
76 | id = "error",
77 | strong("Error: "),
78 | span(id = "errormsg")
79 | )
80 | )
81 | )
82 | ),
83 | conditionalPanel(
84 | condition = "input.cardType == 'html'",
85 | uiOutput("cards")
86 | )
87 | )
88 |
--------------------------------------------------------------------------------
/README.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | output:
3 | github_document:
4 | toc: true
5 | toc_depth: 2
6 | ---
7 |
8 |
9 |
10 |
11 | [](https://travis-ci.org/jennybc/bingo)
12 | [](https://ci.appveyor.com/project/jennybc/bingo)
13 | [](https://codecov.io/gh/jennybc/bingo?branch=master)
14 |
15 |
16 | ```{r, echo = FALSE}
17 | knitr::opts_chunk$set(
18 | collapse = TRUE,
19 | comment = "#>",
20 | fig.path = "README-"
21 | )
22 | # so that the same bingo card will be generated every time
23 | set.seed(10)
24 | ```
25 |
26 | # bingo
27 |
28 | Generate Bingo cards.
29 |
30 | Currently has built-in squares for SuperBowl 50 :football: and data / spreadsheet craziness :chart_with_downwards_trend: and more. Or you can provide your own text for the squares.
31 |
32 | Make printable Bingo cards **without installing anything** via this Shiny app:
33 |
34 | *
35 | * It's also included in the package (see [below](#run-shiny-app-locally)).
36 |
37 | Feel free to help us make these cards less ugly or to explore new bingo topics! PRs welcome :grin:.
38 |
39 | ## Installation
40 |
41 | Install from GitHub with:
42 |
43 | ```{r eval = FALSE}
44 | # install.packages("devtools")
45 | devtools::install_github("jennybc/bingo")
46 | ```
47 |
48 | ## SuperBowl Example
49 |
50 | ```{r}
51 | library(bingo)
52 |
53 | ## see some of the SuperBowl 50 squares
54 | tail(get_topic("football"))
55 |
56 | ## make 8 bingo cards
57 | bc <- bingo(n_cards = 8, words = get_topic("football"))
58 |
59 | ## print them to PDF
60 | plot(bc)
61 | ```
62 |
63 | Here's what one looks like:
64 |
65 | 
66 |
67 | ## "Open" and Bad Data Examples
68 |
69 | We offer two sets of squares inspired by the ~~pain~~ joy of dealing with [`#otherpeoplesdata`](https://twitter.com/search?q=%23otherpeoplesdata&src=tyah)
70 |
71 | Use `get_topic("open-data")` to get squares based on this tweet from Chris McDowall:
72 |
73 | > For two weeks I noted issues encountered as I used NZ govt data. Today I collected enough to make a bingo card. *[\@fogonwater, January 3, 2016](https://twitter.com/fogonwater/status/683785398112260097)*
74 |
75 | Use `get_topic("bad-data")` to get squares inspired by the [Quartz guide to bad data](https://github.com/Quartz/bad-data-guide):
76 |
77 | > An exhaustive reference to problems seen in real-world data along with suggestions on how to resolve them.... Most of these problems can be solved. Some of them can't be solved and that means you should not use the data. Others can't be solved, but with precautions you can continue using the data.
78 |
79 | ```{r}
80 | ## see some Open Data squares
81 | tail(get_topic("open-data"))
82 |
83 | ## see some Bad Data squares
84 | tail(get_topic("bad-data"))
85 |
86 | ## make a single Open Data bingo card
87 | ## Note that "open-data" is the default topic, so you could alternatively use: bc <- bingo().
88 | bc <- bingo(words = get_topic("open-data"))
89 |
90 | ## make a custom bingo blend from the open and bad data squares
91 | bc <- bingo(words = c(get_topic("open-data"), get_topic("bad-data")))
92 |
93 | ## print it
94 | plot(bc, pdf_base = "open-data-")
95 | ```
96 |
97 | Here's an Open Data bingo card:
98 |
99 | 
100 |
101 | ```{r clean-up, include = FALSE}
102 | crap <- c(list.files(pattern = "bingo-[0-9]+.pdf"),
103 | list.files(pattern = "open-data-[0-9]+.pdf"))
104 | file.remove(crap)
105 | ```
106 |
107 | ## Run Shiny app locally
108 |
109 | To run [the app we're running remotely](http://daattali.com/shiny/bingo/) on your own machine, do this:
110 |
111 | ```{r eval = FALSE}
112 | launch()
113 | ```
114 |
115 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [](https://travis-ci.org/jennybc/bingo)
8 | [](https://ci.appveyor.com/project/jennybc/bingo)
10 | [](https://codecov.io/gh/jennybc/bingo?branch=master)
12 |
13 |
14 | # bingo
15 |
16 | Generate Bingo cards.
17 |
18 | Currently has built-in squares for SuperBowl 50 :football: and data /
19 | spreadsheet craziness :chart\_with\_downwards\_trend: and more. Or you
20 | can provide your own text for the squares.
21 |
22 | Make printable Bingo cards **without installing anything** via this
23 | Shiny app:
24 |
25 | -
26 | - It’s also included in the package (see
27 | [below](#run-shiny-app-locally)).
28 |
29 | Feel free to help us make these cards less ugly or to explore new bingo
30 | topics\! PRs welcome :grin:.
31 |
32 | ## Installation
33 |
34 | Install from GitHub with:
35 |
36 | ``` r
37 | # install.packages("devtools")
38 | devtools::install_github("jennybc/bingo")
39 | ```
40 |
41 | ## SuperBowl Example
42 |
43 | ``` r
44 | library(bingo)
45 |
46 | ## see some of the SuperBowl 50 squares
47 | tail(get_topic("football"))
48 | #> [1] "Shot of Golden Gate Bridge"
49 | #> [2] "\"Silicon Valley and tech\" blah blah blah"
50 | #> [3] "Mike Carey is WRONG"
51 | #> [4] "Unexpected artist joins Beyoncé"
52 | #> [5] "Cam's Superman shirt-opening thing"
53 | #> [6] "Idle speculation it's Peyton's last game"
54 |
55 | ## make 8 bingo cards
56 | bc <- bingo(n_cards = 8, words = get_topic("football"))
57 |
58 | ## print them to PDF
59 | plot(bc)
60 | #> Writing to file ...
61 | #> ./bingo-01.pdf
62 | #> ./bingo-02.pdf
63 | #> ./bingo-03.pdf
64 | #> ./bingo-04.pdf
65 | #> ./bingo-05.pdf
66 | #> ./bingo-06.pdf
67 | #> ./bingo-07.pdf
68 | #> ./bingo-08.pdf
69 | ```
70 |
71 | Here’s what one looks like:
72 |
73 | 
74 |
75 | ## “Open” and Bad Data Examples
76 |
77 | We offer two sets of squares inspired by the ~~pain~~ joy of dealing
78 | with
79 | [`#otherpeoplesdata`](https://twitter.com/search?q=%23otherpeoplesdata&src=tyah)
80 |
81 | Use `get_topic("open-data")` to get squares based on this tweet from
82 | Chris McDowall:
83 |
84 | > For two weeks I noted issues encountered as I used NZ govt data. Today
85 | > I collected enough to make a bingo card. *[@fogonwater,
86 | > January 3, 2016](https://twitter.com/fogonwater/status/683785398112260097)*
87 |
88 | Use `get_topic("bad-data")` to get squares inspired by the [Quartz guide
89 | to bad data](https://github.com/Quartz/bad-data-guide):
90 |
91 | > An exhaustive reference to problems seen in real-world data along with
92 | > suggestions on how to resolve them…. Most of these problems can be
93 | > solved. Some of them can’t be solved and that means you should not use
94 | > the data. Others can’t be solved, but with precautions you can
95 | > continue using the data.
96 |
97 | ``` r
98 | ## see some Open Data squares
99 | tail(get_topic("open-data"))
100 | #> [1] "PDF tables" "numbers formatted as text"
101 | #> [3] "metadata expressed as fieldnames" "fieldname EDA"
102 | #> [5] "regex-driven workflow" "named region non-sequiturs"
103 |
104 | ## see some Bad Data squares
105 | tail(get_topic("bad-data"))
106 | #> [1] "Data disguised as formatting"
107 | #> [2] "Ambiguous American date formats, eg 03/04/16"
108 | #> [3] "\"Virgin Birth\", ie no provenance"
109 | #> [4] "Location of 0°N 0°E, ie \"Null Island\""
110 | #> [5] "Spelling mistakes that reek of hand-typed data"
111 | #> [6] "US zip codes 12345 or 90210"
112 |
113 | ## make a single Open Data bingo card
114 | ## Note that "open-data" is the default topic, so you could alternatively use: bc <- bingo().
115 | bc <- bingo(words = get_topic("open-data"))
116 |
117 | ## make a custom bingo blend from the open and bad data squares
118 | bc <- bingo(words = c(get_topic("open-data"), get_topic("bad-data")))
119 |
120 | ## print it
121 | plot(bc, pdf_base = "open-data-")
122 | #> Writing to file ...
123 | #> ./open-data-01.pdf
124 | ```
125 |
126 | Here’s an Open Data bingo card:
127 |
128 | 
129 |
130 | ## Run Shiny app locally
131 |
132 | To run [the app we’re running
133 | remotely](http://daattali.com/shiny/bingo/) on your own machine, do
134 | this:
135 |
136 | ``` r
137 | launch()
138 | ```
139 |
--------------------------------------------------------------------------------