diff --git a/Christmas/2022/ChristmasTree.R b/Christmas/2022/ChristmasTree.R new file mode 100644 index 0000000000000000000000000000000000000000..a4c11f12e9dea562630e5704d591648d395ed27a --- /dev/null +++ b/Christmas/2022/ChristmasTree.R @@ -0,0 +1,178 @@ +ChristmasTree <- function(recipe) { + +# Config +author <- recipe$Description$Title$author +title <- recipe$Description$Title$text +title.col <- recipe$Description$Title$color +bg.col <- strsplit(recipe$background$color, ' ')[[1]] +tree.col <- strsplit(recipe$tree$leaves$color, ' ')[[1]] +trunk.col <- strsplit(recipe$tree$trunk$color, ' ')[[1]] +ball.col <- strsplit(recipe$balls$color, ' ')[[1]] +snow.col <- strsplit(recipe$snow$color, ' ')[[1]] +snow.level <- recipe$snow$level +star <- recipe$star$shape +fileout <- recipe$fileout + +# Sanity checks +if (length(title.col) != 1) stop("Title can only have one color.") +if (length(tree.col) != 1) stop("Tree leaves can only have one color.") +if (length(trunk.col) != 1) stop("Tree trunk can only have one color.") +if (length(bg.col) != 1) stop("Background can only have one color.") +if (length(star) != 1) stop("Star can only have one shape.") +if (!star %in% c('star', 'heart', 'poop', 'smile', 'smirk')) stop("Star can only be star, heart, poop, smile, or smirk.") + +if (!is.null(fileout)) { + png(fileout, width = 480, height = 480) +} else { + dev.new(width = 6.5, height = 6.5) +} + +ll <- 252 + +par(bg = bg.col) +plot(0, xlim = c(-0.75, 0.75), axes = F, xlab = "", ylab = "", ylim = c(-50, ll + 48)) + +# trunk +rect(-0.1, -50, 0.08, 1, col = trunk.col, border = trunk.col) + +# star glow +if (star != 'heart') { + col_star <- rgb(1, 1, 0, 0.05) +} else { + col_star <- rgb(1, 0.6, 0.8, 0.1) +} +for(i in 12:1) { + points(-0.02, ll + 1, pch = 19, col = col_star, cex = 5 + (0.65 * i)) +} + +# Tree +s <- (ll:1)/1000 +a <- 0 +i_seq <- rep(exp(-seq(1, 125, by = 2) * 0.016), 4) * s + s + +if (tree.col == 'green') { + for (i in i_seq) { + a <- a + 1 + j_seq <- seq(-i, i, 0.1) + for (j in j_seq) { + points(j, a, col = rgb(0, i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, 0), + pch = 8, cex = 2.8, lwd = 1.5) + } + } +} else if (tree.col == 'blue') { + for (i in i_seq) { + a <- a + 1 + j_seq <- seq(-i, i, 0.1) + for (j in j_seq) { + points(j, a, col = rgb(0, 0, i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2), + pch = 8, cex = 2.8, lwd = 1.5) + } + } +} else if (tree.col == 'red') { + for (i in i_seq) { + a <- a + 1 + j_seq <- seq(-i, i, 0.1) + for (j in j_seq) { + points(j, a, col = rgb(i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, 0, 0), + pch = 8, cex = 2.8, lwd = 1.5) + } + } +} else if (tree.col == 'yellow') { + for (i in i_seq) { + a <- a + 1 + j_seq <- seq(-i, i, 0.1) + for (j in j_seq) { + points(j, a, col = rgb(i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, 0), + pch = 8, cex = 2.8, lwd = 1.5) + } + } +} else if (tree.col %in% c('gray', 'grey')) { + for (i in i_seq) { + a <- a + 1 + j_seq <- seq(-i, i, 0.1) + for (j in j_seq) { + points(j, a, col = rgb(i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2, i * 0.7 + 0.2 * runif(1, 0.6, 1) - 0.5 * j^2), + pch = 8, cex = 2.8, lwd = 1.5) + } + } +} else { + stop("Tree leaf color is not supported.") +} + +# Christmas bulbs +cols1 <- sample(c(rgb(1, 0, 0, 0.1), rgb(0, 1, 0, 0.1), rgb(1, 1, 0, 0.1), rgb(0, 0.2, 1, 0.1))) +cols2 <- sample(c(rgb(1, 0, 0, 0.1), rgb(0, 1, 0, 0.1), rgb(1, 1, 0, 0.1), rgb(0, 0.2, 1, 0.1))) +cols3 <- sample(c(rgb(1, 0, 0, 0.1), rgb(0, 1, 0, 0.1), rgb(1, 1, 0, 0.1), rgb(0, 0.2, 1, 0.1))) +cols4 <- sample(c(rgb(1, 0, 0, 0.1), rgb(0, 1, 0, 0.1), rgb(1, 1, 0, 0.1), rgb(0, 0.2, 1, 0.1))) + +## small bulbs +for (i in 11:1) { + points(seq(-0.5, 0.5, 0.1), rep(0, 11), pch = 19, cex = 0.15 + (0.12 * i), col = cols1) + points(seq(-0.375, 0.375, 0.1), rep(64.5, 8), pch = 19, cex = 0.15 + (0.12 * i), col = cols2) + points(seq(-0.25, 0.25, 0.1), rep(125, 6), pch = 19, cex = 0.15 + (0.12 * i), col = cols3) + points(seq(-0.125, 0.125, 0.1), rep(189.5, 3), pch = 19, cex = 0.15 + (0.12 * i), col = cols4) +} + +## balls +loc <- c(runif(8, -0.45, 0.45), runif(8, 0, 30)) +points(loc[1:8], loc[9:16], pch = 19, cex = round(runif(8, 1.8, 2.2), digits = 2), + col = sample(ball.col, 8, replace = TRUE)) +loc <- c(runif(6, -0.25, 0.25), runif(6, 65, 100)) +points(loc[1:6], loc[7:12], pch = 19, cex = round(runif(6, 1.8, 2.2), digits = 2), + col = sample(ball.col, 6, replace = TRUE)) +loc <- c(runif(4, -0.15, 0.15), runif(4, 125, 170)) +points(loc[1:4], loc[5:8], pch = 19, cex = round(runif(4, 1.8, 2.2), digits = 2), + col = sample(ball.col, 4, replace = TRUE)) +points(-0.05, 200, pch = 19, cex = 2, col = sample(ball.col, 1)) +# first layer edge +points(sample(c(-0.45, 0.45), 1), 6, pch = 19, cex = 2, col = sample(ball.col, 1)) +# second layer edge +points(sample(c(-0.32, 0.32), 1), 66, pch = 19, cex = 2, col = sample(ball.col, 1)) +# third layer edge +points(sample(c(-0.2, 0.2), 1), 130, pch = 19, cex = 2, col = sample(ball.col, 1)) + +# Star +if (star == 'star') { + points(-0.02, 251, pch = 19, cex = 4.3, col = 7) + points(-0.02, 254, pch = emo::ji(keyword = 'star'), cex = 8, col = 7) +} else if (star == 'heart') { + points(-0.02, 251, pch = emo::ji(keyword = 'heart'), cex = 5, col = 'hotpink') +} else if (star == 'poop') { + points(-0.02, 253, pch = 19, cex = 5, col = 'black') + points(-0.02, 256, pch = emo::ji(keyword = 'poop'), cex = 6, col = 'chocolate4') +} else if (star == 'smile') { + points(-0.02, 253, pch = 19, cex = 7.2, col = rgb(1, 1, 0, alpha = 0.95)) + points(-0.02, 253, pch = emo::ji(keyword = 'smile'), cex = 4, col = rgb(0, 0, 0, alpha = 0.8)) +} else if (star == 'smirk') { + points(-0.02, 253, pch = 19, cex = 7.2, col = rgb(1, 1, 0, alpha = 0.95)) + points(-0.02, 253, pch = emo::ji(keyword = 'smirk'), cex = 4, col = rgb(0, 0, 0, alpha = 0.8)) +} else { + stop("This star type is not supported.") +} + +# Snowflakes +if (snow.level == 'none') { + snow_num <- c(0, 0) +} else if (snow.level == 'below_normal') { + snow_num <- c(40, 60) +} else if (snow.level == 'normal') { + snow_num <- c(80, 100) +} else if (snow.level == 'above_normal') { + snow_num <- c(160, 200) +} +points(runif(snow_num[1], -1, 1), runif(snow_num[1], -50, ll + 60), + col = sample(snow.col, snow_num[1], replace = TRUE), + cex = sample(seq(0.6, 1.5, length.out = snow_num[1])), + pch = emo::ji(keyword = 'snowflake')) +points(runif(snow_num[2], -1, 1), runif(snow_num[2], -50, -45), + col = sample(snow.col, snow_num[2], replace = TRUE), + cex = sample(seq(0.6, 1.5, length.out = snow_num[2])), + pch = emo::ji(keyword = 'snowflake')) + + # Add author + mtext(paste0(author, ' - ', title), side = 1, line = 1, col = title.col) + + if (!is.null(fileout)) { + dev.off() + } +} diff --git a/Christmas/2022/Xmas_Activity_2022.pdf b/Christmas/2022/Xmas_Activity_2022.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e9d5fb7cb2b9d9b33c7d434f82d9e93432fcc346 Binary files /dev/null and b/Christmas/2022/Xmas_Activity_2022.pdf differ diff --git a/Christmas/2022/plot_ChristmasTree.R b/Christmas/2022/plot_ChristmasTree.R new file mode 100644 index 0000000000000000000000000000000000000000..c0da6260a118a693498610385977d992411ad227 --- /dev/null +++ b/Christmas/2022/plot_ChristmasTree.R @@ -0,0 +1,5 @@ +library(yaml) +source('ChristmasTree.R') +recipe <- read_yaml('recipe_ChristmasTree_template.yml') + +ChristmasTree(recipe) diff --git a/Christmas/2022/recipe_ChristmasTree_template.yml b/Christmas/2022/recipe_ChristmasTree_template.yml new file mode 100644 index 0000000000000000000000000000000000000000..fecdb3d294dbb247fd3fd62d2696b8b9b3f5a7ad --- /dev/null +++ b/Christmas/2022/recipe_ChristmasTree_template.yml @@ -0,0 +1,21 @@ +Description: + Title: + author: BSCES + text: All I want for Christmas is... + color: 'white' # One random color for title +background: + color: 'navy' # One random color, e.g., 'lightblue', '#612794', 2 +tree: + leaves: + color: 'green' # One of the following: 'green', 'blue', 'red', 'yellow', 'grey' + trunk: + color: 'darkgoldenrod4' # One random color, e.g., 'darkgoldenrod4', '#5829C4', 1 +balls: + color: oldlace lightcyan lightgoldenrod1 # Multiple random colors +snow: + level: normal # One of the following: 'none', 'below_normal', 'normal', 'above_normal' + color: ghostwhite lightsteelblue1 # Multiple random colors +star: + shape: "star" # One of the following: 'star', 'heart', 'poop', 'smile', 'smirk' +fileout: './xmasTree.png' # NULL (pop-up window) or a valid full file path, e.g., '~/xmasTree.png' + diff --git a/Christmas/2022/xmasTree.png b/Christmas/2022/xmasTree.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc222b91a7a62f156dde52e70c9992f5ef3ce4b Binary files /dev/null and b/Christmas/2022/xmasTree.png differ