Skip to content

Commit a182759

Browse files
authored
Program and logos #46 (#47)
* #38 and #44 * update * Program and logos #46 * update * test harmonization * corrections * logo correction * some corrections
1 parent a46aa3f commit a182759

File tree

12 files changed

+248
-83
lines changed

12 files changed

+248
-83
lines changed

R/schedule.R

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
library(dplyr)
2+
library(stringr)
3+
library(kableExtra)
4+
5+
# ---- Read + clean program ----
6+
df <- read.csv(program_csv, stringsAsFactors = FALSE, na.strings = c("", "NA")) |>
7+
mutate(
8+
day = as.integer(day),
9+
time = str_trim(time),
10+
type = str_trim(type),
11+
author = str_trim(coalesce(author, "")),
12+
title = str_trim(coalesce(title, "")),
13+
info = str_trim(coalesce(info, ""))
14+
) |>
15+
arrange(day, time)
16+
17+
# Optional: shorten repeated phrasing
18+
df$author <- gsub("Contributed\\s*from\\s*submitted\\s*abstracts", "Contributed abstracts", df$author)
19+
df$author <- gsub("Contributed\\s*until\\s*the\\s*beginning\\s*of\\s*the\\s*conference", "Contributed pre-conference", df$author)
20+
21+
# Day headers (edit dates if needed)
22+
day_headers <- c(
23+
"Day 1 — Wed. Sep 17, 2025",
24+
"Day 2 — Thu. Sep 18, 2025",
25+
"Day 3 — Fri. Sep 19, 2025"
26+
)
27+
28+
# ---- Read palette (optional) ----
29+
pal <- if (file.exists(colors_csv)) {
30+
read.csv(colors_csv, stringsAsFactors = FALSE) |>
31+
mutate(
32+
type = str_trim(type),
33+
color = str_trim(color)
34+
)
35+
} else {
36+
data.frame(type = character(), color = character())
37+
}
38+
39+
# Attach color per row (keeps row order)
40+
df2 <- df |>
41+
left_join(pal, by = "type")
42+
43+
# Output table data
44+
df_out <- df2 |> select(time, type, author, title)
45+
46+
# Row indices by day
47+
idx_by_day <- split(seq_len(nrow(df_out)), df2$day)
48+
49+
# ---- Build table ----
50+
tbl <- kbl(
51+
df_out,
52+
escape = TRUE,
53+
row.names = FALSE,
54+
col.names = c("Time", "Type", "Author", "Title")
55+
) |>
56+
kable_material(full_width = TRUE) |>
57+
column_spec(1, width = "12%") |>
58+
column_spec(2, width = "18%") |>
59+
column_spec(3, width = "28%") |>
60+
column_spec(4, width = "42%")
61+
62+
# ---- Apply row colors from CSV ----
63+
for (i in seq_len(nrow(df2))) {
64+
bg <- df2$color[i]
65+
if (!is.na(bg) && nzchar(bg)) {
66+
tbl <- tbl |> row_spec(i, background = bg)
67+
}
68+
}
69+
70+
# ---- Group by day (only if that day exists) ----
71+
for (d in seq_along(day_headers)) {
72+
key <- as.character(d)
73+
if (!is.null(idx_by_day[[key]])) {
74+
tbl <- tbl |>
75+
pack_rows(
76+
day_headers[d],
77+
min(idx_by_day[[key]]),
78+
max(idx_by_day[[key]])
79+
)
80+
}
81+
}
82+
83+
tbl |> cat()

R/sponsors.R

Lines changed: 105 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1-
# R/sponsors.R ---------------------------------------------------------------
21

32
read_sponsors <- function(csv_path) {
43
read.csv(csv_path, stringsAsFactors = FALSE)
54
}
65

7-
# Helper: join prefix + path safely (works for URLs and relative paths)
86
url_join <- function(prefix, path) {
97
if (is.null(prefix) || prefix == "") return(path)
8+
9+
# Keep "/" as site-root prefix
10+
if (identical(prefix, "/")) {
11+
path <- sub("^/+", "", path)
12+
return(paste0("/", path))
13+
}
14+
1015
prefix <- sub("/+$", "", prefix)
1116
path <- sub("^/+", "", path)
1217
paste0(prefix, "/", path)
1318
}
1419

15-
# ---- (1) Harmonize one logo into a fixed canvas and save it ----------------
20+
21+
# ---- (1) Harmonize one logo into a fixed canvas and save it
1622
harmonize_logo <- function(input_fs,
1723
output_fs,
1824
canvas_w = 800,
@@ -21,23 +27,23 @@ harmonize_logo <- function(input_fs,
2127
if (!requireNamespace("magick", quietly = TRUE)) {
2228
stop("Package 'magick' is required for harmonization. Install with install.packages('magick').")
2329
}
24-
30+
2531
img <- magick::image_read(input_fs)
26-
32+
2733
# Scale logo to fit inside (canvas - padding) while preserving aspect ratio
2834
target_w <- max(1, canvas_w - 2 * padding)
2935
target_h <- max(1, canvas_h - 2 * padding)
30-
36+
3137
img2 <- magick::image_resize(img, geometry = paste0(target_w, "x", target_h, ">"))
32-
38+
3339
# Create transparent canvas and center the resized logo
3440
canvas <- magick::image_blank(width = canvas_w, height = canvas_h, color = "none")
3541
composed <- magick::image_composite(canvas, img2, operator = "over", gravity = "center")
36-
42+
3743
# Ensure output directory exists
3844
out_dir <- dirname(output_fs)
3945
if (!dir.exists(out_dir)) dir.create(out_dir, recursive = TRUE, showWarnings = FALSE)
40-
46+
4147
magick::image_write(composed, path = output_fs, format = "png")
4248
invisible(output_fs)
4349
}
@@ -50,50 +56,57 @@ harmonize_sponsor_logos <- function(df,
5056
canvas_h = 240,
5157
padding = 24) {
5258
stopifnot("image" %in% names(df))
53-
59+
60+
# If magick missing, do nothing (keep original df$image)
5461
if (!requireNamespace("magick", quietly = TRUE)) {
5562
warning("Package 'magick' not installed; skipping harmonization.")
5663
return(df)
5764
}
58-
59-
# Create a copy so we can overwrite df$image to point to harmonized images
65+
6066
df2 <- df
61-
67+
6268
for (i in seq_len(nrow(df2))) {
6369
in_rel <- df2$image[i]
64-
in_fs <- url_join(fs_prefix, in_rel)
65-
66-
# Make stable output filename
70+
71+
# filesystem input (prefix applies)
72+
in_fs <- file.path(fs_prefix, in_rel)
73+
74+
# stable output name
6775
base <- tools::file_path_sans_ext(basename(in_rel))
68-
out_rel <- file.path(harmonized_dir, paste0(base, ".png"))
69-
out_fs <- out_rel
70-
71-
# Only (re)render if missing, or input is newer
72-
need <- TRUE
73-
if (file.exists(out_fs) && file.exists(in_fs)) {
74-
need <- file.info(out_fs)$mtime < file.info(in_fs)$mtime
75-
} else if (file.exists(out_fs) && !file.exists(in_fs)) {
76-
# If input_fs is not readable in this working dir, don't overwrite
77-
need <- FALSE
78-
}
79-
80-
if (need && file.exists(in_fs)) {
81-
harmonize_logo(
82-
input_fs = in_fs,
83-
output_fs = out_fs,
84-
canvas_w = canvas_w,
85-
canvas_h = canvas_h,
86-
padding = padding
87-
)
76+
out_rel <- file.path(harmonized_dir, paste0(base, ".png")) # WEB PATH (no fs_prefix)
77+
out_fs <- file.path(fs_prefix, out_rel) # FILESYSTEM PATH
78+
79+
# Only harmonize if we can read the input
80+
if (file.exists(in_fs)) {
81+
82+
# render if missing or stale
83+
need <- !file.exists(out_fs) ||
84+
(file.info(out_fs)$mtime < file.info(in_fs)$mtime)
85+
86+
if (need) {
87+
harmonize_logo(
88+
input_fs = in_fs,
89+
output_fs = out_fs,
90+
canvas_w = canvas_w,
91+
canvas_h = canvas_h,
92+
padding = padding
93+
)
94+
}
95+
96+
# Only switch to harmonized image if the file actually exists
97+
if (file.exists(out_fs)) {
98+
df2$image[i] <- out_rel
99+
}
100+
} else {
101+
# input not found -> keep original df2$image[i]
102+
# (this is the critical difference vs your current code)
88103
}
89-
90-
# Point to the harmonized relative path for rendering
91-
df2$image[i] <- out_rel
92104
}
93-
105+
94106
df2
95107
}
96108

109+
97110
# ---- (2) Render grid; optionally harmonize and USE harmonized images --------
98111
render_sponsor_grid <- function(df,
99112
ncol = 4,
@@ -104,15 +117,17 @@ render_sponsor_grid <- function(df,
104117
harmonized_dir = "images/partners_harmonized",
105118
canvas_w = 800,
106119
canvas_h = 240,
107-
padding = 24) {
120+
padding = 24,
121+
left_margin = 10,
122+
inner_width = 80) {
108123
stopifnot(all(c("image", "website") %in% names(df)))
109124
if (nrow(df) == 0) return(invisible(NULL))
110-
111-
ncol <- min(ncol, nrow(df))
125+
126+
ncol <- min(ncol, nrow(df))
112127
width <- floor(100 / ncol)
113-
114-
# Harmonize first (updates df$image to harmonized paths)
115-
if (harmonize) {
128+
129+
# If you want to harmonize on render time, do it here (optional)
130+
if (isTRUE(harmonize)) {
116131
df <- harmonize_sponsor_logos(
117132
df,
118133
fs_prefix = fs_prefix,
@@ -121,62 +136,72 @@ render_sponsor_grid <- function(df,
121136
canvas_h = canvas_h,
122137
padding = padding
123138
)
139+
} else {
140+
# Even if we don't harmonize now, prefer an already-existing harmonized image
141+
for (i in seq_len(nrow(df))) {
142+
base <- tools::file_path_sans_ext(basename(df$image[i]))
143+
harm_rel <- file.path(harmonized_dir, paste0(base, ".png"))
144+
harm_fs <- file.path(fs_prefix, harm_rel)
145+
if (file.exists(harm_fs)) df$image[i] <- harm_rel
146+
}
124147
}
125-
126-
out <- c()
148+
149+
out <- character()
150+
127151
out <- c(out, ":::: {.columns}")
128-
out <- c(out, "::: {.column width=\"10%\"}")
152+
out <- c(out, sprintf("::: {.column width=\"%s%%\"}", left_margin))
129153
out <- c(out, ":::")
130-
out <- c(out, "::: {.column width=\"90%\"}", "")
154+
out <- c(out, sprintf("::: {.column width=\"%s%%\"}", inner_width), "")
131155
out <- c(out, ":::: {.columns}")
132-
156+
133157
for (i in seq_len(nrow(df))) {
134-
# df$image is now the harmonized relative path (or original if harmonize=FALSE)
135158
img_src <- url_join(web_prefix, df$image[i])
136-
159+
alt_txt <- ""
160+
137161
out <- c(out, sprintf("::: {.column width=\"%s%%\"}", width))
138-
162+
163+
# Quarto supports target="_blank" on markdown links with an attribute block
164+
# If your setup doesn’t, you can remove `{target="_blank"}`
139165
out <- c(out, sprintf(
140-
"<a href='%s' target='_blank' class='sponsor-link'>%s</a>",
141-
df$website[i],
142-
sprintf(
143-
"<img src='%s' alt='%s' class='sponsor-logo'>",
144-
img_src,
145-
if ("name" %in% names(df)) df$name[i] else "Sponsor logo"
146-
)
166+
"[![%s](%s)](%s){target=\"_blank\"}",
167+
alt_txt, img_src, df$website[i]
147168
))
148-
149-
if (show_name && ("name" %in% names(df)) && nzchar(df$name[i])) {
150-
out <- c(out, sprintf("<div class='sponsor-name'>%s</div>", df$name[i]))
169+
170+
if (isTRUE(show_name) && ("name" %in% names(df)) && nzchar(df$name[i])) {
171+
out <- c(out, "", df$name[i])
151172
}
152-
173+
153174
out <- c(out, ":::")
154175
}
155-
176+
156177
out <- c(out, "::::", "")
178+
out <- c(out, ":::") # close inner width column
179+
out <- c(out, sprintf("::: {.column width=\"%s%%\"}", left_margin))
157180
out <- c(out, ":::")
158-
out <- c(out, "::: {.column width=\"10%\"}")
159-
out <- c(out, ":::")
160-
out <- c(out, "::::")
161-
181+
out <- c(out, "::::") # close outer columns
182+
162183
cat(paste(out, collapse = "\n"))
163184
}
164185

186+
165187
render_sponsors_home <- function(csv_path, title = "", ncol = 4,
188+
fs_prefix = "",
189+
web_prefix = "",
166190
harmonize = TRUE,
167191
harmonized_dir = "images/partners_harmonized") {
168192
df <- read_sponsors(csv_path)
169-
cat(sprintf("# %s\n\n", title))
193+
170194
render_sponsor_grid(
171195
df,
172196
ncol = ncol,
173-
fs_prefix = "",
174-
web_prefix = "",
197+
fs_prefix = fs_prefix,
198+
web_prefix = web_prefix,
175199
harmonize = harmonize,
176200
harmonized_dir = harmonized_dir
177201
)
178202
}
179203

204+
180205
render_sponsors_by_level <- function(
181206
csv_path,
182207
level_order = c("Diamond", "Gold", "Silver", "Bronze", "Supporter"),
@@ -188,28 +213,28 @@ render_sponsors_by_level <- function(
188213
harmonized_dir = "images/partners_harmonized"
189214
) {
190215
heading <- match.arg(heading)
191-
216+
192217
df <- read_sponsors(csv_path)
193218
if (!("level" %in% names(df))) stop("CSV must include a 'level' column.")
194-
219+
195220
df$level <- factor(df$level, levels = level_order)
196-
221+
197222
levels_present <- unique(as.character(df$level))
198223
levels_present <- level_order[level_order %in% levels_present]
199-
224+
200225
for (lvl in levels_present) {
201226
df_lvl <- df[as.character(df$level) == lvl, , drop = FALSE]
202227
if (nrow(df_lvl) == 0) next
203-
228+
204229
if (heading == "h2") {
205230
cat(sprintf("\n## %s\n\n", lvl))
206231
} else {
207232
cat(sprintf("\n**%s**\n\n", lvl))
208233
}
209-
234+
210235
ncol <- unname(ncol_by_level[lvl])
211236
if (is.na(ncol)) ncol <- 4
212-
237+
213238
render_sponsor_grid(
214239
df_lvl,
215240
ncol = ncol,

_quarto.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ website:
1313
title: false
1414
collapse-below: lg
1515
right:
16-
#- href: pages/schedule.qmd
16+
- href: pages/schedule.qmd
1717
- href: pages/speakers.qmd
1818
- href: pages/submissions.qmd
1919
- href: pages/registration.qmd

0 commit comments

Comments
 (0)