Skip to content

Commit cb54634

Browse files
committed
A04Ca_charts added
1 parent 6405ac0 commit cb54634

File tree

3 files changed

+212
-1
lines changed

3 files changed

+212
-1
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: BioDataScience1
2-
Version: 2023.4.0
2+
Version: 2023.4.1
33
Title: A Series of Learnr Documents for Biological Data Science 1
44
Description: Interactive documents using learnr and shiny applications for studying biological data science.
55
Authors@R: c(

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# BioDataScience1 2023.4.1
2+
3+
- Shiny application A04Ca_charts for ranking challenge results is added.
4+
15
# BioDataScience1 2023.4.0
26

37
- Learnrs A04La_barplot, A04Lb_boxplot and A04Lc_comp_fig ready.

inst/shiny/A04Ca_charts/app.R

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Input solution for the challenge and get ranking
2+
# ================================================
3+
# Note: the shared folder is created like this using SSH onto the server
4+
# cd /data1
5+
# sudo mkdir A04_challenge
6+
# sudo chown rstudio-connect: A04_challenge
7+
8+
# We also need flipdown from:
9+
#remotes::install_github("feddelegrand7/flipdownr")
10+
11+
library(data.io)
12+
#library(mlearning)
13+
library(RSQLite)
14+
library(flipdownr)
15+
16+
# Indicate title and deadline here
17+
title <- "Challenge graphiques"
18+
# Note: define real deadline in environment variables in RStudio Connect
19+
deadline <- Sys.getenv("CHALLENGE_DEADLINE",
20+
unset = "2024-01-01 00:00:00")
21+
22+
# Read data from the SQLite database
23+
dir <- "/data1/A04_challenge"
24+
if (!file.exists(dir))
25+
dir <- "~/A04_challenge" # Alternate dir for local tests
26+
database <- file.path(dir, "charts.sqlite")
27+
table <- "charts"
28+
29+
# Is the countdown over?
30+
is_done <- function()
31+
as.POSIXct(deadline) < Sys.time()
32+
33+
# If the time difference between current date and countdown
34+
# is more than 100 days, we consider the next challenge has not started yet
35+
not_started_yet <- function()
36+
difftime(Sys.time(), as.POSIXct(deadline), units = "days") > 100
37+
38+
# The function that calculates score and returns also a message
39+
score_charts <- function(x) {
40+
if (!is.numeric(x) | length(x) != 20)
41+
return(structure(NA,
42+
message = "Le fichier doit contenir un objet numérique de longueur 20. Corrigez et resoumettez !"))
43+
if (any(x < 0) | any(x > 1))
44+
return(structure(NA,
45+
message = paste("Le r\u00e9sultat doit contenir des valeurs entre 0 et 1 uniquement. Corrigez et resoumettez !")))
46+
score <- as.numeric(sum(x)) # Score is the sum of all the 20 individual scores for the different charts
47+
structure(score,
48+
message = paste0("Votre proposition est accept\u00e9e. Son score est de ",
49+
round(score, 1), "."))
50+
}
51+
52+
# Manage results into the SQLite database
53+
empty_data <- function()
54+
data.frame(project = character(0), model = character(0),
55+
date = as.POSIXct(character(0)), score = numeric(0))
56+
57+
save_data <- function(data) {
58+
# Connect to the database
59+
db <- dbConnect(SQLite(), database)
60+
# Make sure table exists in the database
61+
try(dbWriteTable(db, table, empty_data()), silent = TRUE)
62+
# Construct the update query by looping over the data fields
63+
query <- sprintf(
64+
"INSERT INTO %s (%s) VALUES ('%s')",
65+
table,
66+
paste(names(data), collapse = ", "),
67+
paste(data, collapse = "', '")
68+
)
69+
# Submit the update query and disconnect
70+
dbSendStatement(db, query)
71+
dbDisconnect(db)
72+
}
73+
74+
load_data <- function() {
75+
# Connect to the database
76+
db <- dbConnect(SQLite(), database)
77+
# Construct the fetching query
78+
query <- sprintf("SELECT * FROM %s", table)
79+
# Submit the fetch query and disconnect
80+
data <- try(dbGetQuery(db, query), silent = TRUE)
81+
dbDisconnect(db)
82+
if (inherits(data, "try-error")) {
83+
empty_data()
84+
} else {
85+
data
86+
}
87+
}
88+
89+
ui <- fluidPage(
90+
titlePanel(title),
91+
92+
sidebarLayout(
93+
sidebarPanel(
94+
fileInput("file", "Votre proposition (fichier RDS)", accept = ".rds"),
95+
textOutput("message"),
96+
hr(),
97+
actionButton("refresh", "Actualiser le classement")
98+
),
99+
mainPanel(
100+
h3("Temps restant pour le challenge :"),
101+
flipdown(downto = deadline, id = "csfrench", theme = "dark",
102+
headings = c("jours", "heures", "minutes", "secondes")),
103+
hr(),
104+
h3("Classement :"),
105+
tableOutput("ranking")
106+
)
107+
)
108+
)
109+
110+
server <- function(input, output) {
111+
output$message <- renderText({
112+
file <- input$file
113+
ext <- tools::file_ext(file$datapath)
114+
req(file)
115+
validate(need(ext == "rds", "Vous devez indiquer un fichier RDS"))
116+
# Check that there is still time remaining
117+
if (is_done()) {
118+
if (not_started_yet()) {
119+
"Ce challenge n'a pas encore commenc\u00e9, attendez le d\u00e9part !"
120+
} else {
121+
"Ce challenge est fini, vous ne pouvez plus soumettre de proposition !"
122+
}
123+
} else {
124+
# Check that filename is correct (repos__model.rds)
125+
if (!grepl("^.+__.+\\.rds", file$name)) {
126+
"Le nom de votre fichier est incorrect : il faut <repos>__<iteration>.rds. Corrigez et resoumettez."
127+
} else {
128+
#solution <- data.io::read$rds(file$datapath)$value
129+
solution <- data.io::read$rds(file$datapath)
130+
# Check if a model of the same name already exists
131+
name <- file$name
132+
project <- sub("(^.+)__.+$", "\\1", name)
133+
model <- sub(("^.+__(.+)\\.rds$"), "\\1", name)
134+
ranking <- load_data()
135+
if (NROW(ranking[ranking$project == project & ranking$model == model, ])) {
136+
"Cette it\u00e9ration existe dans le classement, recompilez le document avant de soumettre une nouvelle variante."
137+
} else {
138+
attr(score_charts(solution), "message")
139+
}
140+
}
141+
}
142+
})
143+
144+
output$ranking <- renderTable({
145+
input$refresh # Trigger this code when the refresh button is clicked
146+
file <- input$file
147+
if (!is.null(file$datapath) && grepl("^.+__.+\\.rds", file$name) &&
148+
!is_done()) {
149+
#solution <- data.io::read$rds(file$datapath)$value
150+
solution <- data.io::read$rds(file$datapath)
151+
message("data read")
152+
score <- score_charts(solution)
153+
message("score is ", score)
154+
name <- file$name
155+
message("name is ", name)
156+
project <- sub("(^.+)__.+$", "\\1", name)
157+
model <- sub(("^.+__(.+)\\.rds$"), "\\1", name)
158+
if (project == name) {
159+
message("Wrong name!")
160+
score <- NA
161+
}
162+
} else {
163+
score <- NA
164+
}
165+
ranking <- load_data()
166+
message("Data loaded")
167+
# Record an entry in the mongoDB database
168+
# But we need the login of *all* members of the team, and we don't have them
169+
# right now => leave this to a post-process task instead!
170+
if (!is.na(score)) {
171+
# Check if it is not submitted yet
172+
if (!NROW(ranking[ranking$project == project & ranking$model == model, ])) {
173+
save_data(list(
174+
project = project, model = model, date = Sys.time(),
175+
score = as.numeric(score)
176+
))
177+
# Reload the full dataset
178+
ranking <- load_data()
179+
}
180+
}
181+
# Rework the ranking table
182+
if (NROW(ranking)) {
183+
ranking <- ranking[order(-ranking$score, as.numeric(ranking$date)), ]
184+
ranking$date <- as.POSIXct(ranking$date, origin = "1960-01-01")
185+
ranking$date <- format(ranking$date, "%Y-%m-%d %H:%M:%S")
186+
}
187+
message("Date reworked")
188+
# Add a column with medals for the three first results
189+
n <- NROW(ranking)
190+
if (n == 0) {
191+
medals <- character(0)
192+
} else {
193+
medals <- c("\U1F947", "\U1F948", "\U1F949")
194+
if (n < 4) {
195+
medals <- medals[1:n]
196+
} else {
197+
medals <- c(medals, rep("", n - 3))
198+
}
199+
}
200+
ranking <- data.frame(rank = medals, ranking)
201+
message("Ranking done")
202+
names(ranking) <- c("", "Projet", "It\u00e9ration", "Date", "Score")
203+
ranking
204+
})
205+
}
206+
207+
shinyApp(ui, server)

0 commit comments

Comments
 (0)