# librerie utilizzato -----------------------------------------------------
library(tidyverse) # per i comandi della programmazione funzionale
                   # (map e dintorni)
library(quarto)    # per sfruttare la funzione quarto_render

# esempio di utilizzo di quarto_render ------------------------------------

# la funzione quarto_render permette la compilazione (rendering)
# di un report Quarto sfruttando il codice: è l'equivalente del
# tasto render dell'interfaccia
# se non utilizzo i parametri previsti nel modello di report parametrico
# viene compilato il report con i valori di default presenti nella sezione
# YAML del file .qmd
quarto_render(input = "report-parametrico.qmd",
              output_format = "html",
              output_file = "report-parametrico-default.html")

# sfruttando la funzione quarto_render posso personalizzare il report
# passando in input i parametri di interesse del particolare report
# sfruttando l'argomento execute_params
quarto_render(input = "report-parametrico.qmd",
              execute_params = list(anno = 1952,
                                    continente = "Asia"),
              output_format = "html",
              output_file = "report-asia-1952.html")

# la funzione list.files permette di ottenere la lista dei file presenti
# in una data cartella (per default la cartella corrente)
# posso specificare un pattern di ricerca: in questo caso cerco tutti i
# file che iniziano con la stringa "report" e terminano con l'estensione
# ".html"
list.files(pattern = "^report-.*\\.html")

# cancello i due file html creati nei due esempi precedenti in modo da
# automatizzare la procedura di creazione dei vari report sotto
file.remove(list.files(pattern = "^report-.*\\.html"))


# quanti sono i possibili report? -----------------------------------------

# il numero di report che posso ottenere a partire da questo semplice
# modello dipendono dal numero di anni distinti presenti nella tabella
# NOTA: uso la funzione pull() per ottenere un output di tipo atomico
anni <- gapminder::gapminder |> distinct(year) |> pull()
anni
# e dal numero di continenti
continenti <- gapminder::gapminder |> distinct(continent) |> pull()
continenti
# poichè i continenti sono codificati come una variabile di tipo factor
# e il parametro del report parametrico è di tipo stringa  converto
# il vettore atomico in un vettore di caratteri
continenti <- gapminder::gapminder |> 
  distinct(continent) |> 
  pull() |> 
  as.character()
continenti

# il numero di possibili report è pari al prodotto tra il numero di continenti
length(continenti)
# e il numero di anni presenti nella tabella dati
length(anni)
# posso ottenere una tabella che riporta tutti i possibili incroci
# sfruttando la funzione expand_grid passando in input i due vettori atomici
incroci <- expand_grid(continenti, anni)
incroci
nrow(incroci)

# una nota sulla concatenazione di stringhe -------------------------------

# le funzioni paste e paste0 consentono agevolmente di concatenare stringhe
# la prima usa uno spazio come separatore tra le varie stringhe mentre
# la secondo non usa alcun separatore
paste("Ciao", "Pippo", "benvenuto nel mondo delle stringhe")
paste0("Ciao", "Pippo", "benvenuto nel mondo delle stringhe")


# funzione map e varianti -------------------------------------------------

# la funzione map {purrr} permette di "applicare" una funzione (secondo 
# argomento) a tutti gli elementi di una struttura passata come primo argomento
map(.x = c(1, 2, 3, 4, 5), .f = log)
# la funzione map restituisce una lista ma è possibile chiedere di semplificare
# la struttura di output sfruttando la variante map_vec
map_vec(.x = c(1, 2, 3, 4, 5), .f = log)
# se è necessario passare in input argomenti aggiuntivi alla funzione si
# può utilizzare la sintassi con la tilde prima del nome della funzione
# esempio: calcolo del logaritmo del numero 100 usando differenti le basi
#          per il logaritmo passate come primo argomento
map_vec(.x = c(1, 2, 3, 4, 5), .f = ~log(100, .x))
# nel caso in cui non sono interessato all'outuput quanto all'effetto
# collaterale di una funzione (esempio: salvataggio di un file o stampa
# di un grafico) posso sfruttare la funzione walk
walk(.x = c(1, 2, 3, 4, 5), 
     .f = ~print(paste("Stampo il numero:", .x)))

# la funzione map2 (walk2) è analoga alla funzione map (walk) con la
# differenza che la funzione (terzo argomento) è applicata considerando
# tutte le possibili coppie passate come primo e secondo argomento
map2(.x = c(10, 20, 30), .y = c(1, 2, 3), .f = ~log(x = .x, base = .y))
map2_vec(.x = c(10, 20, 30), .y = c(1, 2, 3), .f = ~log(x = .x, base = .y))
walk2(.x = c(10, 20, 30), 
     .y = c(1, 2, 3), 
     .f = ~print(paste0("calcolo f su ", .x, " e ", .y)))

# report per tutti i continenti per un dato anno --------------------------

# se sono interessato ad ottenere i report dei vari continenti per un dato
# anno posso costruire un vettore con i nomi dei file di output desiderati
nomi_file <- paste0("report-", continenti, "-1952.html")
nomi_file

# e sfruttare la funzione walk2 (o map2)
walk2(.x = continenti, 
      .y = nomi_file,
      .f = ~quarto_render(input = "report-parametrico.qmd",
                          execute_params = list(anno = 1952,
                                                continente = .x),
                          output_format = "html",
                          output_file = .y)) 

# file creati automaticamente sfruttando la funzione walk2
list.files(pattern = "^report-.*\\.html")
# cancello i file html creati in questo test della funzione walk2
# (vedi codice sotto per la procedura completa)
file.remove(list.files(pattern = "^report-.*\\.html"))


# report per un dato continente per tutti i possibili anni ----------------

# se sono interessato ad ottenere i report dei vari continenti per un dato
# anno posso costruire un vettore con i nomi dei file di output desiderati
nomi_file <- paste0("report-Europa-", anni, ".html")
nomi_file

# e sfruttare la funzione walk2 (o map2)
walk2(.x = anni, 
      .y = nomi_file,
      .f = ~quarto_render(input = "report-parametrico.qmd",
                          execute_params = list(anno = .x,
                                                continente = "Europe"),
                          output_format = "html",
                          output_file = .y)) 

# file creati automaticamente sfruttando la funzione walk2
list.files(pattern = "^report-.*\\.html")
# cancello i file html creati in questo test della funzione walk2
# (vedi codice sotto per la procedura completa)
file.remove(list.files(pattern = "^report-.*\\.html"))


# report per tutti i possibili incroci ------------------------------------

# per ottenere tutti i possibili report sfrutto la funzione expand_grid
# introdotta in precedenza 
# aggiungo una colonna con i nomi dei file di output
incroci <- expand_grid(continenti, anni) |> 
  mutate(nomi = paste0("report-", continenti, "-", anni, ".html"))
incroci  

# e sfrutto la funzione pwalk (o pmap) per ottenere tutti i report

# un esempio di pmap: creo un vettore con i tre elementi presenti
# su ogni riga della tabella incroci
pmap(incroci, 
    ~c(a = ..1, b = ..2, c = ..3))
# un esempio di pwalk: stampo i tre elementi presenti su ogni riga
# della tabella incroci
pwalk(incroci, 
      ~print(paste0("El. 1 -> ", ..1, 
                    " | El. 2 -> ", ..2, 
                    "| El. 3 -> ", ..3)))

# sfruttando la funzione pwalk posso ottenere tutti i 60 report
# in modo automatico incrociando tutti i possibili valori di anno e 
# continente (prime due colonne della tabella incroci) e passando
# i nomi dei file di output desiderati (terza colonna)
pwalk(incroci, 
      ~quarto_render(input = "report-parametrico.qmd",
                     execute_params = list(anno = ..2,
                                           continente = ..1),
                     output_format = "html",
                     output_file = ..3))

# file creati automaticamente sfruttando la funzione pwalk
list.files(pattern = "report-*.html")

# sposto i file creati nella cartella report
# NOTA: creo la directory se non già presente sul disco 
dir.create("report", showWarnings = FALSE)
file.rename(from = list.files(pattern = "report-.*\\.html"),
            to = paste0("report/", list.files(pattern = "report-.*\\.html")))
