Utilizzando Google Moduli per la didattica, molti insegnanti avvertono la mancanza di alcune funzionalità che permettano di utilizzarli come verifiche digitali: ad esempio la possibilità di impostare ora e data di apertura e chiusura, oppure il tempo massimo per svolgere la prova, magari con un timer che indica il tempo rimasto allo studente. Lo anticipiamo fin da subito: ad oggi molte di queste possibilità non sono opzioni di Google Moduli. Né si possono ottenere, come spesso proponiamo su questo blog, con la programmazione di Apps Script.

Questo perché allo stato attuale tutte le funzioni e i metodi degli script relativi ai moduli agiscono solo sull’interfaccia dell’editor. Modificano cioè la visualizzazione del proprietario o del collaboratore che crea e imposta il modulo. Non agiscono invece sull’interfaccia dell’utente che compila: non è quindi possibile interagire con gli studenti mostrando il tempo rimasto, chiudendo automaticamente il modulo allo scadere, e così via. Possiamo quindi ottenere nativamente o con Apps Script solo alcune delle funzionalità indicate sopra.

Questo articolo offre la procedura definitiva e testata rispetto a quella già proposta in via sperimentale nell’articolo Test – Aprire e chiudere automaticamente modulo Google. Puoi controllare i commenti di quel post per alcune richieste e relative risposte.

I componenti aggiuntivi: vantaggi e avvertenze

I componenti aggiuntivi di Google Moduli offrono spesso qualche modalità di lavoro aggiuntiva che nelle verifiche si può rivelare utile. Bisogna però prestare particolare attenzione in questo caso. Alcuni di essi – FormLimiter, per citare uno dei più famosi – offrono solo alcune opzioni base tra quelle elencate sopra. Agiscono cioè solo sull’interfaccia dell’editor, e semplificano l’impostazione di scenari che si possono raggiungere anche con gli script.

Altri invece – per fare un esempio, Extended Forms – mostrano possibilità più avanzate, ma lo fanno ad una condizione ben precisa. L’utente finale (lo studente nel nostro caso) non apre più direttamente il modulo Google nella pagina nativa; il modulo viene invece aperto all’interno di un’altra pagina web, di proprietà del gestore del componente aggiuntivo. Proprio perchè il modulo viene incorporato in una pagina web diversa, è possibile mostrare al compilatore tutto quello che normalmente è precluso nell’interfaccia utente di Moduli. Questo comporta però – oltre a qualche passaggio più laborioso nell’impostazione – il concedere al componente aggiuntivo l’accesso ai dati dell’account Google. Di conseguenza, dobbiamo avere grande fiducia nello sviluppatore, controllare adeguatamente il trattamento dei dati, e valutare in che modo questo influisce anche sui dati di chi compila (che per noi spesso saranno studenti non maggiorenni) e non solo di chi crea il modulo.

Utilizzare Apps Script

Al di là delle avvertenze particolari appena accennate, in alcuni casi potremmo desiderare di non utilizzare componenti aggiuntivi esterni, anche se fidati. Le stesse funzionalità offerte dai componenti aggiuntivi che non si appoggiano su servizi esterni possono essere facilmente implementate con Apps Script. L’ambiente di programmazione interno e integrato in G Suite implica diversi vantaggi. Primo fra tutti, nel nostro caso, la possibilità di leggere il codice sorgente e sapere esattamente cosa fa. Quando andiamo ad accettare i permessi, se siamo noi ad inserire il codice in Apps Script possiamo controllare di preciso cosa succede, se i dati restano all’interno del dominio o meno, ecc. Aspetto da non sottovalutare in ambito scolastico.

Abbiamo già visto precedentemente come limitare i Moduli Google in base al numero massimo di risposte, utile non tanto in caso di verifiche o test, quanto più per uno scenario di iscrizioni a numero chiuso. Vediamo in questo post una delle funzionalità che può facilmente adattare Google Moduli per le verifiche, o attività analoghe. Impostiamo una data e ora di apertura e di chiusura del modulo. Possiamo decidere di impostare una sola delle due, oppure entrambe: lo script attiverà e disattiverà automaticamente la raccolta delle risposte in base alle impostazioni date.

Apertura e chiusura automatica del modulo

Prima di tutto crea il modulo che vorrai utilizzare, struttura domande e risposte e modifica le impostazioni in base alle tue esigenze. Poi segui le indicazioni qui di seguito: trovi un promemoria veloce e spiegazioni più dettagliate, scegli quelle che preferisci, portano allo stesso risultato.

A. Indicazioni veloci

Se hai già usato Apps Script, ti basta seguire questi passaggi

  1. vai nel menu in alto a destra, 3 pallini verticali, e apri Editor di script, quindi dai un nome al progetto di test
  2. elimina la funzione vuota predefinita, incolla il codice che trovi qui sotto e salva con l’icona apposita
  3. controlla che sia selezionata (sulla barra dell’editor in alto) la funzione onOpen, quindi clicca su Esegui ed accetta le autorizzazioni
  4. torna nel modulo, clicca l’icona a forma di puzzle Componenti aggiuntivi e scegli la voce con il nome del progetto che hai appena assegnato al test
  5. scegli Imposta inizio e fine compilazione, segui le indicazioni per impostare apertura e/o chiusura automatica e testa il funzionamento prima di sottoporre il modulo agli studenti

B. Percorso dettagliato

Se non hai confidenza con l’ambiente di Apps Script, queste indicazioni riportano lo stesso percorso indicato sopra in maniera più dettagliata:

  • vai nel menu in alto a destra, clicca sui 3 pallini verticali, e quindi su Editor di script
  • clicca in alto su Progetto senza nome, dai un nome a tua scelta al progetto e clicca su Rinomina
apps script rinomina
  • elimina la funzione vuota che trovi nell’editor function myFunction... avendo cura di eliminare anche tutte le parentesi; quindi copia e incolla il codice che trovi più sotto, e salva con l’icona apposita in alto a sinistra
  • controlla che sia selezionata (sulla barra dell’editor in alto) la funzione onOpen, quindi clicca su Esegui ed accetta le autorizzazioni
  • torna nel modulo, clicca l’icona a forma di puzzle Componenti aggiuntivi e scegli la voce con il nome del progetto che hai appena assegnato al test
Google moduli per le verifiche - Impostazioni
  • scegli Imposta inizio e fine compilazione, segui le indicazioni per impostare apertura e/o chiusura automatica e testa il funzionamento prima di sottoporre il modulo agli studenti

Cosa fa lo script

  • permette di impostare data e ora di apertura e di chiusura del modulo, entrambe o una sola delle due
  • crea uno/due attivatori automatici, che all’ora stabilita attivano e/o disattivano la raccolta delle risposte senza intervento manuale del proprietario
  • se viene scelta una data di inizio, l’attivatore inoltre si occupa di disattivare la raccolta delle risposte da subito, per poi riaprirla quando indicato
  • ad ogni nuova impostazione, elimina di default tutti gli attivatori precedenti, per non generare potenziali conflitti nascosti – attenzione a questo aspetto, se crei attivatori manualmente sullo stesso modulo, questi andranno persi
  • effettua alcuni controlli sui dati inseriti, per prevenire errori nel formato di data e ora
  • accetta la data in diversi formati (dd/mm/yyyy, dd-mm-yyyy, dd.mm.yyyy); accetta giorni, mesi e ore ad una cifra sia con lo 0 iniziale che senza; si occupa di normalizzare automaticamente tutte queste varianti

Cosa non fa lo script

  • non permette di inserire un tempo massimo di compilazione slegato da ora di inizio e fine
  • non permette interazione con il compilatore; le impostazioni agiscono solo a monte, a livello di modulo del proprietario
  • in caso si voglia impostare sia l’inizio che la fine, permette di impostare solo un intervallo di tempo: non è possibile indicare più finestre di compilazione (ad es. dal 2 al 9 gennaio 2021, e anche dal 3 al 9 marzo 2021)

Il codice

// lo script permette di impostare un inizio e/o una fine di compilazione del modulo
// se impostate, verranno creati degli attivatori automatici che apriranno e/o chiuderanno il modulo automaticamente


function onOpen() {
  // la funzione crea un menu aggiuntivo nell'interfaccio grafica di moduli, da cui sarà possibile gestire tutta la procedura
  var ui = FormApp.getUi();
  ui.createAddonMenu().addItem('Imposta inizio e fine compilazione', 'impostaInizioFine').addToUi();
}

function impostaInizioFine() {
  // funzione principale, avviata dal menu Componenti aggiuntivi

  var ui = FormApp.getUi();
  var regexData = new RegExp(/^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/);
  var regexOra = new RegExp(/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/);
  
  // viene chiesto all'utente se vuole impostare data di inizio compilazione
  // diversamente, si passa alla richeista di impostazione di fine compilazione
  var impostaInizio = ui.alert(`Vuoi impostare una data e ora di inizio compilazione?
  Scegli SÌ per impostarle, NO per proseguire con il passaggio successivo.`,  ui.ButtonSet.YES_NO);
  if (impostaInizio == ui.Button.YES) {
    var dataInizio = acquisisciDataOra(ui, `Inserisci la data di inizio compilazione. Rispetta il formato gg/mm/aaaa, ad es 15/12/2020.`, regexData);
    var oraInizio = acquisisciDataOra(ui, `Inserisci l'ora di inizio compilazione. Rispetta il formato hh:mm, ad es 10:30.`, regexOra);
    var inizio = new Date (dataInizio.split(dataInizio.charAt(dataInizio.length - 5)).map(x => normalizzaDataOra(x)).reverse().join('-') + 'T' + oraInizio.split(':').map(x => normalizzaDataOra(x)).join(':'));

  }
  
  var impostaFine = ui.alert(`Vuoi impostare una data e ora di fine compilazione?
  Scegli SÌ per impostarle, NO per proseguire con il passaggio successivo.`,  ui.ButtonSet.YES_NO);
  if (impostaFine == ui.Button.YES) {
    var dataFine = acquisisciDataOra(ui, `Inserisci la data di fine compilazione. Rispetta il formato gg/mm/aaaa, ad es 15/12/2020.`, regexData);
    var oraFine = acquisisciDataOra(ui, `Inserisci l'ora di fine compilazione. Rispetta il formato hh:mm, ad es 10:30.`, regexOra);
    var fine = new Date (dataFine.split(dataFine.charAt(dataFine.length - 5)).map(x => normalizzaDataOra(x)).reverse().join('-') + 'T' + oraFine.split(':').map(x => normalizzaDataOra(x)).join(':'));
  }
  
  if ((inizio) & (fine) & (fine <= inizio)) {
    ui.alert(`Hai inserito un termine della compilazione precedente o uguale all'inizio della compilazione.
    Rivedi i dati inseriti, quindi potrai proseguire.`);
    // impostaInizioFine();
    return;
  }

  var stringaProcedi = '';
  if (inizio) {
    stringaProcedi += `Hai selezionato l'inizio della compilazione per le ore ${oraInizio} del ${dataInizio}: il modulo verrà ora chiuso, e riaperto al momento stabilito.`;
  } else {
    stringaProcedi += `Non hai selezionato un inizio della compilazionem il modulo resterà compilabile o meno già da ora in base all'impostazione manuale che darai.`;
  }
  if (fine) {
    stringaProcedi += `Hai selezionato la fine della compilazione per le ore ${oraFine} del ${dataFine}: il modulo verrà chiuso automaticamente in quel momento.`;
  } else {
    stringaProcedi += `Non hai selezionato una fine per la compilazione del modulo: continuerà ad accettare risposte fino ad un tuo intervento manuale.`;
  }
  stringaProcedi += `Se questi dati sono corretti, clicca OK per procedere, altrimenti scegli ANNULLA.
  Nota che procedendo verranno eliminati gli eventuali attivatori precedentemente associati allo script.`;

  var procedi = ui.alert(stringaProcedi, ui.ButtonSet.OK_CANCEL);
  // se premuto Annulla, termina lo script
  if (procedi == ui.Button.CANCEL) {
    return;
  }

  // se premuto Ok, elimina i trigger precedentemente impostati
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }

  // imposta trigger di inizio compilazione, se impostata
  if (inizio) {

    // disattiva compilazione da questo momento
    disattivaCompilazione();
    // imposta trigger per inizio compilazione
    ScriptApp.newTrigger('attivaCompilazione')
    .timeBased()
    .at(inizio)
    .inTimezone('Europe/Rome')
    .create();
  }
  
  // imposta trigger di fine compilazione, se impostata
  if (fine) {
    ScriptApp.newTrigger('disattivaCompilazione')
    .timeBased()
    .at(fine)
    .inTimezone('Europe/Rome')
    .create();
  }
}


// --------- funzioni ausiliarie

// acquisisce risposta dal prompt, e verifica la corrispondenza del formato data/ora
// se non corrisponde, avvisa l'utente e ripete la richiesta
function acquisisciDataOra(ui, promptText, regex) {
  var response = ui.prompt(promptText).getResponseText();
  if (!regex.test(response)) {
    ui.alert(`Errore nell'inserimento dei dati. Premi OK e riprova.`);
    response = acquisisciDataOra(ui, promptText, regex);
  }
  return response;
}

// aggiunge lo 0 se mancante in ora, giorno e mese
function normalizzaDataOra(x) {
  if (x.length == 1) {
    x = "0" + x;
  }
  return x;
}

function attivaCompilazione() {
  var form = FormApp.getActiveForm();
  form.setAcceptingResponses(true);
}

function disattivaCompilazione() {
  var form = FormApp.getActiveForm();
  form.setAcceptingResponses(false);
}

Se hai domande sul funzionamento, o incontri problemi nell’impostazione o esecuzione dello script, puoi usare i commenti qui sotto.

This error message is only visible to WordPress admins

Error: No connected account.

Please go to the Instagram Feed settings page to connect an account.