Caratteristiche tecniche

Il primo passo nella realizzazione di una piattaforma web consiste normalmente nella definizione della base di dati incaricata di memorizzare le informazioni necessarie al suo funzionamento. Le principali entità coinvolte all’interno del database dell’applicazione Argo Plus sono:

  • User, incaricata di contenere le informazioni personali degli utenti registrati;
  • Campaign, incaricata di contenere le informazioni collegate alla campagna e al suo funzionamento;
  • Task, incaricata di contenere le specifiche del singolo task.

Alcune delle entità contenute all’interno della base di dati sono necessarie al funzionamento di Django, per questo motivo esse vengono generate automaticamente dal framework in fase di installazione come conseguenza dell’esecuzione della prima migration.

Nella gestione delle basi di dati, una migrazione dello schema (schema migration) è una procedura di modifica o aggiornamento dello schema eseguito rispettando le direttive definite a livello di codice, al fine di aggiungere nuove entità oppure migliorare quelle già esistenti (per aggiungere funzionalità o risolvere degli errori). Durante lo sviluppo della piattaforma sono state generate numerose migration. Le entità interessate dalla prima migrazione di Django sono:

  • User, contiene gli utenti iscritti alla piattaforma;
  • Group, contiene i gruppi gestiti dalla piattaforma;
  • Permission, contiene i permessi associati agli utenti e ai gruppi esistenti nella piattaforma.

Di seguito viene mostrato lo schema ER del database “djangodb” (il database dell’applicazione) così come si presenta al termine della sua realizzazione:

Definizione di una applicazione in Django

All’interno del capitolo dedicato all’introduzione al mondo del crowdsourcing, ad Argo Plus e al framework Django, si è parlato della correlazione esistente tra il framework in esame e il pattern MVC (Model – View – Controller), vediamo ora come tale correlazione è stata gestita dai progettisti di Django.

Un progetto sviluppato mediante un framework che adotta il pattern MVC è costituito da tre componenti distinte:

  • Model, responsabili della gestione dei dati e delle regole a loro associati. Essi forniscono ad esempio i metodi dedicati alla manipolazione e all’estrapolazione delle informazioni memorizzate (ad esempio mediante un database relazionale);
  • View, incaricate della rappresentazione grafica (sotto una qualsiasi forma) delle informazioni;
  • Controller, responsabili dell’interpretazione e dell’esecuzione dei comandi esercitati dall’utente attraverso la view.

All’interno dell’applicazione queste tre componenti collaborano tra loro per portare a compimento i comandi impartiti dall’utente. Ad esempio: si consideri una pagina contenente un form di registrazione ad un sito, per il funzionamento di tale pagina e per il completamento della procedura di registrazione richiesta dall’utente sarà necessario l’intervento di tutte le componenti sopra citate. All’arrivo sulla pagina di registrazione l’utente si troverà davanti un insieme di campi da compilare presentati in maniera più o meno elegante attraverso le istruzioni impartite nella view (principalmente mediante codice HTML e CSS). Una volta completato il caricamento dei campi richiesti l’utente eseguirà il submit che porterà all’invio di tutti i dati al controller e successivamente al model (talvolta è possibile che i dati inseriti nella view vengano inviati direttamente al model).

Il controller eseguirà una serie di operazioni previste dal programmatore (verifica e modifica dei dati) e successivamente invierà i dati al model avviando le operazioni di salvataggio (creazione del nuovo utente). Il model utilizzerà le informazioni sulle strutture dati in suo possesso per verificare i dati forniti dall’utente, tra questi:

  • Verifica sulla tipologia dei dati forniti in accordo con la tipologia dei campi in cui memorizzare le informazioni (esempio: stringhe troppo lunghe, valore decimali inseriti al posto di valori interi e così via);
  • Verifica sulla presenza dei dati obbligatori;
  • Verifiche avanzate previste dall’utente (esempio: codice fiscale sintatticamente corretto, eccetera).

Successivamente si interfaccerà con il database incaricato di memorizzare le informazioni e inserirà i dati forniti dall’utente. Completato il processo di scrittura delle informazioni il model invierà un feedback al controller che a sua volta modificherà la view per comunicare all’utente l’esito della registrazione.

I progettisti di Django hanno dichiarato di essersi ispirati al modello del MVC durante lo sviluppo del framework senza però seguirne fedelmente le linee guida. All’interno di Django i controller sono stati ad esempio denominati “view”, mentre le viste sono chiamate “template”. Inoltre, è bene sottolineare come malgrado numerosi framework scritti in altri linguaggi preferiscano utilizzare uno specifico model per ogni entità presente nel database (a mio parere facilitando la lettura del codice) in Django le informazioni riguardanti tutte le entità sono inserite all’interno del medesimo file (come avviene anche per il codice di tutti i controller e di tutte le viste). Infine, Django divide i controller utilizzati nel frontend della piattaforma da quelli utilizzati nell’area amministrativa inserendo quest’ultimi in un file dedicato, denominato “admin.py”.

Il backend

Il primo passo nella realizzazione di un’applicazione Django consiste nella realizzazione delle classi dei model collegate alle entità presenti all’interno del database. Come abbiamo già evidenziato tali classi vanno sviluppate all’interno del file “model.py” contenuto all’interno della cartella dell’applicazione. Di seguito viene mostrato il codice del model “Worker”:

class Worker(models.Model):
  id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
  genre = models.CharField(verbose_name=u"Genre", max_length=1)
  birth_date = models.DateField(verbose_name=u"Birth Date")
  w_score = models.DecimalField(verbose_name=u"Score", max_digits=5, decimal_places=2)
  w_trustworthiness = models.DecimalField(verbose_name=u"Trustworthiness", max_digits=4, decimal_places=2)
  banned = models.BooleanField(verbose_name=u"Banned", default=False)

  class Meta:
    verbose_name = "Worker"
    verbose_name_plural = "Workers"

  def __unicode__(self):
    name = self.id.first_name + " " +self.id.last_name + " - " + self.id.username
    return name

  def __str__(self):
    name = self.id.first_name + " " +self.id.last_name + " - " + self.id.username
    return name

Inizialmente vengono definiti i campi del model a cui sono associate alcune informazioni (tipologia di valore accettato, chiavi esterne, valori di default, eccetera). Successivamente vengono definite alcune caratteristiche collegate al model, come ad esempio il nome da associare alle singole istanze. Infine, vengono definiti i metodi “__unicode__” e “__str__” (i corrispettivi del metodo “toString” del linguaggio Java) da utilizzare per esprimere il valore della singola istanza.

Una volta completata la definizione di tutti i model della piattaforma sarà possibile passare alla definizione dei controller (definiti all’interno del file “admin.py”). Non esiste una struttura standard da utilizzare per la realizzazione di un controller Django (nel caso specifico del backend), esistono comunque un certo numero di metodi di uso comune la cui riscrittura porterà alla modifica delle principali componenti della piattaforma. Di seguito viene mostrata la struttura base del controller “Campaign”.

class CampaignAdmin(admin.ModelAdmin):
  list_per_page = 15
  list_display = ('name', 'requester', 'campaign_status', 'start_date', 'finish_date', 'start_signup', 'finish_signup')
  list_filter = ['campaign_status']
  ordering = ['start_date', 'name']
  search_fields = ['name']

  def changelist_view(self, request, extra_context=None):
    extra_context = extra_context or {}
    return super(CampaignAdmin, self).changelist_view(request, extra_context=extra_context)

  def get_form(self, request, obj=None, **kwargs):
    return CampaignAdminForm

  def get_fieldsets(self, request, obj=None):
    return [...]

  def save_model(self, request, obj, form, change):
    ...

  def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
    extra_context = extra_context or {}
    return super(CampaignAdmin, self).changeform_view(request, object_id=object_id, form_url=form_url, extra_context=extra_context)

  def history_view(self, request, object_id, extra_context=None):
    extra_context = extra_context or {}
    return super(CampaignAdmin, self).history_view(request, object_id=object_id, extra_context=extra_context)

  def delete_view(self, request, object_id, extra_context=None):
    extra_context = extra_context or {}
    return super(CampaignAdmin, self).delete_view(request, object_id=object_id, extra_context=extra_context)

admin.site.register(Campaign, CampaignAdmin)

Mediante l’utilizzo dei metodi appena descritti è possibile controllare il funzionamento della maggior parte delle funzioni del controller e delle pagine ad esso collegate, in particolare le pagine normalmente collegate ad un controller sono:

  • Changelist, pagina riepilogo di tutte le istanze inserite per un certo oggetto. La pagina contiene una tabella in grado di rappresentare tutte le istanze inserite dall’utente per l’oggetto in questione (alcuni framework utilizzano semplicemente il termine “view” per denominare tale pagina);
  • Changeform, pagina contenente il form di inserimento/modifica delle informazioni per l’oggetto corrente (alcuni framework utilizzano i termini “add” o “update” per identificare tale pagina);
  • History, contiene la storia delle modifiche apportate all’istanza dell’oggetto includendo i dati personali dell’utente che le ha eseguite;
  • Delete, permette la rimozione dell’istanza selezionata e di quelle ad essa collegate.

All’interno del frammento di codice precedente i campi posti in cima alla classe hanno lo scopo principale di personalizzare il comportamento della pagina di changelist, in particolare:

  • “list_per_page”, definisce il numero di elementi che saranno contenuti all’interno di ogni pagina (limite di paginazione);
  • “list_display”, definisce le colonne della tabella della changelist (e di conseguenza le informazioni che saranno mostrate a video);
  • “list_filter”, definisce i filtri che potranno essere applicati;
  • “ordering”, definisce i campi di ordinamento predefiniti;
  • “search_fields”, definisce i campi su cui verrà eseguita la ricerca.

Di seguito viene mostrata un’immagine della pagina di changelist contenente i dati di due campagne, nella colonna di destra sono visibili i filtri che possono essere applicati alla pagina per scremare i dati mostrati, mentre nella parta alta è visibile il pulsante di inserimento e la ricerca.

La select posta sotto al nome del model (in questo caso “Campaigns”) contiene le azioni che possono essere applicate alle istanze dopo averle selezionate.

Segue un riepilogo dei metodi presentati all’interno del frammento di codice:

  • “changelist_view”, modifica il comportamento della pagina di changelist;
  • “get_form”, definisce il form da utilizzare all’interno del changeform;
  • “get_fieldsets”, definisce la suddivisione dei campi all’interno del sopracitato form;
  • “save_model”, definisce le operazioni da effettuare prima del salvataggio dei dati;
  • “changeform_view”, modifica il comportamento della pagina di changeform;
  • “history_view”, modifica il comportamento della pagina di history;
  • “delete_view”, modifica il comportamento della pagina di delete.

Infine, dopo aver definito i model e i controller sarà possibile procedere con la definizione dei form (che altrimenti sarebbero generati dal framework a run-time). Nella definizione del form occorre elencare tutti i campi che si vuole rappresentare sotto forma di input e la tipologia di input HTML da utilizzare, inoltre si definiscono anche i metodi di pulizia dei singoli campi nonché il metodo di pulizia globale (entrambi opzionali). Di seguito viene mostrato il codice del form “CampaignAdminForm” responsabile della creazione e della modifica delle campagne da parte degli amministratori.

class CampaignAdminForm(forms.ModelForm):
  name = forms.CharField(label='Name')
  requester = forms.ModelChoiceField(label='Requester', help_text='Select user from the "Requester" group', queryset=User.objects.filter(groups__name__iexact='requester').order_by('username'))
  campaign_status = forms.ModelChoiceField(label='Status', queryset=Campaign_Status.objects.order_by('name').all())
  start_signup = forms.CharField(label='Start Signup', widget=forms.DateInput(attrs={'type': 'date'}))
  finish_signup = forms.CharField(label='Finish Signup', widget=forms.DateInput(attrs={'type': 'date'}))
  start_date = forms.CharField(label='Start Date', widget=forms.DateInput(attrs={'type': 'date'}))
  finish_date = forms.CharField(label='Finish Date', widget=forms.DateInput(attrs={'type': 'date'}))
  init_trustworthiness = forms.DecimalField(label='Trustworthiness', help_text='Enter the required minimum value', widget=forms.NumberInput(), initial=1, min_value=1, decimal_places=2)

  # taskjson #
  taskjson = forms.CharField(label='JSON', help_text='View the help section for more information', widget=forms.Textarea, required=False)
  # taskjson #

  class Meta:
    model = Campaign
    fields = ('name', 'requester', 'campaign_status', 'start_signup', 'finish_signup', 'start_date', 'finish_date', 'init_trustworthiness', 'taskjson')

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
      for field in self._meta.fields:
        if self.fields[field].required:
          attrs = {'class': 'form-control required'}
        else:
          attrs = {'class': 'form-control'}
        self.fields[field].widget.attrs.update(attrs)

  def clean_taskjson(self):
    ...

  def clean(self):
    ...

All’interno dei metodi denominati “clear_nomeCampo” (come ad esempio “clear_taskjson”) vengono eseguite le operazioni di verifica dei dati inseriti dall’utente all’interno dello specifico campo (esse vengono definite dal programmatore). All’interno del metodo “clean” possono essere invece inserite le operazioni di verifica “globali”, ovvero in grado di mettere in relazione i dati provenienti da più campi del form (ad esempio è possibile verificare che due date inserite in un form non si sovrappongano). I metodi di pulizia “locali” (come ad esempio “clear_taskjson”) possono estendere i metodi nativi di Django, i quali verificano i dati inseriti sfruttando le informazioni contenute nel model (come ad esempio la tipologia del dato inserito).

Gli Inline Formset

Un’importante caratteristica offerta dal framework Django risiede nella possibilità di creare pagine di inserimento/modifica costituite da form comprendenti quelli che Django chiama gli “Inline Formset”. Un inline formset non è altro che un form HTML destinato all’inserimento delle istanze di un model che viene incluso all’interno di un altro form (destinato ad un altro model) per un certo numero di volte stabilito dall’utente.

Gli inline formset sono stati utilizzati in diverse occasioni all’interno della piattaforma Argo Plus:

  1. In fase di modifica della campagna sono utilizzati per permettere l’inserimento e la modifica dei task ad essa associati;
  2. In fase di creazione e di modifica di un task sono utilizzati per permettere l’inserimento e la modifica delle possibili risposte (in caso di task di tipo “chosen”), delle configurazioni e delle skill associate.

Utilizzando un inline formset (collegato ad una certa istanza e ad un certo form) l’utente può inserire svariate istanze appartenenti ad un oggetto, le quali saranno in qualche modo legate all’oggetto padre inserito mediante il form principale. In fase di modifica l’utente potrà scegliere di inserire nuovi elementi, modificare quelli già inseriti, oppure rimuoverli. All’interno di un form così costituito non sarà possibile inserire l’istanza definita mediante inline formset senza inserire quella collegata al form principale (non sarà possibile inserire un task senza inserire anche la campagna).

Di seguito viene mostrata l’immagine di una parte del form di inserimento e modifica dei task all’interno del quale è ben visibile l’inline formset di inserimento dei task-setup. Il pulsante “Add Another” posizionato all’interno dell’inline formset dei task-setup permette l’aggiunta di un nuovo modulo di inserimento (in questo caso per un’altra configurazione), mentre nella parte bassa della pagina sono invece visibili i tre pulsanti di salvataggio contenuti all’interno di tutto il form.

Caratteristiche tecniche di Argo Plus

Dopo aver definito all’interno del secondo capitolo “Analisi dei requisiti” i requisiti dell’utilizzatore finale della piattaforma, analizziamo in questo terzo capitolo le caratteristiche implementate in Argo Plus per sopperire a tali necessità.

Per la realizzazione dell’interfaccia grafica si è scelto di utilizzare il tema gratuito Gentelella (github), tuttavia durante lo sviluppo della piattaforma si è resa necessaria la sua quasi totale riscrittura al fine di correggere i numerosi errori riscontrati nella sua implementazione. Per la realizzazione del tema (e per la sua successiva modifica) sono stati utilizzati i linguaggi HTML5, CSS3, JavaScript, JQuery e il framework grafico Bootstrap.

Bootstrap

L’utilizzo di bootstrap (e della sua struttura modulare a griglia) permette la realizzazione di layout responsive (con struttura adattiva), accessibili dalla maggior parte dei device e dei browser in commercio.

La struttura di una pagina HTML sviluppata con bootstrap è piuttosto elementare, l’interfaccia grafica viene suddivisa in righe (identificate dalle classi “row”) e successivamente in colonne (identificate dalle classi con prefisso “col-“). Ogni colonna di un layout sviluppato in bootstrap è caratterizzata da un peso che viene rappresentato mediante un numero intero posto come suffisso della classe (che assume quindi una struttura simile a questa “col-*-5”). Il peso della classe (rappresentabile mediante un numero intero compreso tra 1 e 12) determina la larghezza che andrà ad occupare l’elemento in questione rispetto al suo genitore. È importante sottolineare come all’interno di ogni riga la somma dei pesi dovrà essere sempre minore o uguale a 12.

In accordo con la documentazione ufficiale (reperibile sul sito getbootstrap.com) viene riportato di seguito qualche esempio pratico:

<div class="row">
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
  <div class="col-md-1">.col-md-1</div>
</div>
<div class="row">
  <div class="col-md-8">.col-md-8</div>
  <div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
  <div class="col-md-4">.col-md-4</div>
  <div class="col-md-4">.col-md-4</div>
  <div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
  <div class="col-md-6">.col-md-6</div>
  <div class="col-md-6">.col-md-6</div>
</div>

Il risultato ottenuto dall’utilizzo del precedente frammento di codice HTML viene mostrato nell’immagine successiva.

Dal frammento di codice deduciamo le già citate caratteristiche di bootstrap:

  • Le righe vengono scritte l’una di seguito all’altra;
  • All’interno di ogni riga trovano posto le colonne;
  • Il peso di ogni colonna dovrà essere compreso tra 1 e 12;
  • La somma dei pesi di una riga dovrà essere minore di 12 (in caso di righe incomplete, ovvero la cui somma dei pesi è inferiore a 12, verrà mostrato uno spazio vuoto a destra di dimensione uguale al peso non utilizzato);
  • All’interno di una colonna potranno essere inserite nuove righe così da creare una struttura ricorsiva.

La forza di bootstrap risiede principalmente nella sua capacità di adattarsi e comportarsi in maniera non uniforme a seconda delle caratteristiche del device in uso. A questo scopo bootstrap offre diversi marcatori utilizzabili al fine di attribuire pesi diversi alle colonne a seconda delle caratteristiche del device. In particolare:

  • “col-xs-*”, definisce il layout per i device con schermi di dimensione inferiore ai 768px;
  • “col-sm-*”, definisce il layout per i device con schermi di dimensione compresa tra 768px e 992px;
  • “col-md-*”, definisce il layout per i device con schermi di dimensione compresa tra 992px e 1200px;
  • “col-lg-*”, definisce il layout per i device con schermi di dimensione superiore ai 1200px.

Associando classi diverse al medesimo blocco è quindi possibile ottenere un comportamento differente da parte di quest’ultimo a seconda del device in uso dall’utente.

Interfaccia di Argo Plus

Seguendo la struttura grafica proposta dai progettisti del tema Gentelella l’interfaccia di Argo Plus si suddivide in due sezioni distinte: nella parte destra dello schermo trova posto il menù a scomparsa laterale con voci a drop-down, mentre nella restante porzione dello schermo (la “main area”) trovano posto i contenuti principali. All’interno dell’header sono ben visibili i dati personali dell’utente collegato (username e avatar), con i collegamenti utili al cambio della password e al logout che sono stati posizionati in un menù a scomparsa. All’interno del footer sono infine stati inseriti i loghi del progetto “Liquid Crowd Project” e di ISLAB.

Interfaccia generale dell’applicazione Argo Plus:

All’interno del menù laterale i diversi collegamenti sono raggruppati in menù e sotto-menù, in modo da ridurre lo spazio necessario alla loro rappresentazione e a facilitarne la ricerca. Le voci sono così distribuite:

  • Campaign
    • Add, punta al modulo di inserimento delle campagne
    • Manage, punta al riepilogo delle campagne
    • Task
      • Manage, punta al riepilogo dei task
      • Task Choice, punta al riepilogo delle scelte dei task (per task di tipo choice)
      • Task Setup, punta al riepilogo delle configurazioni dei task
      • Task Skill, punta al riepilogo delle abilità dei task
    • Workers
      • Manage, punta al riepilogo per iscrizioni alle campagne
      • Worker Task, punta al riepilogo per le risposte alle campagne
  • Workers
    • Add, punta al modulo di inserimento dei lavoratori (nel sistema)
    • Manage, punta al riepilogo dei lavoratori (nel sistema)
  • Utility
    • Answer Type, punta al riepilogo delle tipologie disponibili per i task
    • Campaign Status, punta al riepilogo degli stati disponibili per le campagne
    • Setup
      • Items, punta al riepilogo delle configurazioni disponibili per i task
      • Pattern, punta al riepilogo dei pattern disponibili nel sistema
      • Pattern Setup, punta al riepilogo delle associazioni pattern-setup
    • Skill
      • Items, punta al riepilogo delle abilità disponibili per i task
      • Profile, punta al riepilogo dei profili disponibili nel sistema
      • Profile Skill, punta al riepilogo delle associazioni profile-skill
    • Task Status, punta al riepilogo degli stati dei task

Ad ogni pagina del sistema è associata un diverso livello di autorizzazione, in generale se un utente non è autorizzato ad accedere ad una certa pagina della piattaforma, esso non vedrà nemmeno la corrispondente voce di menù. Le autorizzazioni della piattaforma saranno trattate in un capitolo successivo.

Per facilitare l’utilizzo dell’applicazione sui dispositivi mobile, il menù assume la classica configurazione detta ad “hamburger menù” che gli permette di scomparire lateralmente senza occupare spazio all’interno dell’interfaccia. All’interno della “main area” della piattaforma i contenuti sono organizzati in blocchi di dimensione variabile e riducibili mediante effetto JQuery di tipo toggle.

Infine, per rappresentare l’immagine del profilo utente si è scelto di utilizzare il servizio gratuito Gravatar al fine di alleggerire il carico della piattaforma e semplificare lo sviluppo della funzionalità. Gravatar è un servizio online (purtroppo poco utilizzato in Italia, ma molto usato nel nuovo continente) che permette all’utente, dopo la registrazione al sito, di associare un’immagine personale al proprio indirizzo email così da riutilizzarla in futuro nei siti web supportati. Tra i numerosi siti internet che sfruttano questo servizio citiamo ad esempio il CMS WordPress.

All’interno di Argo Plus un utente registrato a Gravatar non dovrà fare altro che inserire il proprio indirizzo email all’interno del profilo per vedere apparire la propria immagine profilo all’interno dell’interfaccia. In caso contrario verrà visualizzata un’immagine di default. Il vantaggio offerto da questo sistema consiste nel fatto che l’immagine dell’utente (il suo avatar) non verrà ospitata sul server dell’applicazione, ma su quello di Gravatar, portando ad un cospicuo risparmio di spazio.

Grafici e Statistiche

Nella realizzazione della piattaforma Argo Plus sono state utilizzate alcune librerie Javascript/JQuery al fine di aggiungere alcuni effetti grafici e migliorare l’esperienza utente. Tra le librerie installate troviamo:

  • Bootstrap, per gestire gli effetti grafici dell’interfaccia;
  • Chart.js, per la realizzazione dei grafici statistici;
  • FontAwesome, per le icone nel menù ed altri elementi grafici;
  • JQuery, per l’esecuzione delle altre librerie;
  • MalihuCustomScrollbarPlugin, per la realizzazione della scrollbar del menù laterale;
  • Select2, per la realizzazione delle select con ricerca avanzata.

I grafici sviluppati mediante la libreria Chart.js sono contenuti all’interno dell’home page del sito e rappresentano alcune statistiche di interesse, tra queste troviamo:

  • Il numero di lavoratori e il numero di risposte (espresse mediante un grafico a barre) delle ultime 10 campagne inserite nel sistema (globalmente se l’utente è un amministratore, localmente se l’utente è un requester);
  • Sesso dei lavoratori, rappresentato mediante un grafico a torta (visibile solo se l’utente è un administrator);
  • Età dei lavoratori, espresso mediante un grafico a torta suddiviso per range di età (visibile solo se l’utente è un administrator).

All’interno dell’home page sono inoltre contenute alcune informazioni espresse in forma tabellare, tra queste:

  • Le ultime cinque campagne attualmente in esecuzione (globalmente se l’utente è un amministratore, localmente se l’utente è un requester);
  • Le prime cinque campagne prossime all’esecuzione, ovvero la cui data di apertura è vicina alla data odierna (globalmente se l’utente è un amministratore, localmente se l’utente è un requester);
  • Le cinque skill più utilizzate all’interno della piattaforma;
  • Gli ultimi cinque lavoratori iscritti alle campagne (globalmente se l’utente è un amministratore, localmente se l’utente è un requester).

Statistiche aggiuntive sono visualizzate all’interno delle varie sezioni riepilogative del portale, in particolare:

  • Riepilogo “Campagna”, viene mostrato il numero di task contenuti all’interno della campagna, il numero di lavoratori che coinvolge e il numero di risposte che sono state fornite. In aggiunta tali dati sono messi a confronto con quelli delle altre campagne presenti nel sistema (sempre seguendo la logica del requester che vede solo le sue campagne e dell’amministratore che ha invece visione globale);
  • Riepilogo “Task”, vengono mostrate in forma tabellare tutte le risposte fornite dai lavoratori. Ogni riga della tabella contiene: i riferimenti al lavoratore, la risposta fornita e il numero di lavoratori che hanno dato la medesima risposta (tale sistema è ovviamente più preciso nei task di tipo choice);
  • Riepilogo “Lavoratore – Campagna”, viene mostrato lo score ottenuto dal lavoratore nella campagna, il suo score globale e il numero di risposte che ha fornito. In aggiunta tali dati sono messi a confronto con quelli degli altri lavoratori iscritti alla medesima campagna;
  • Riepilogo “Lavoratore – Task”, viene mostrato lo score ottenuto dal lavoratore nella campagna selezionata in relazione al suo score globale. Inoltre, viene mostrato un messaggio che informa se la risposta fornita dal lavoratore nel task è corretta (“Correct”), oppure non corretta (“Incorrect”), ovviamente questa informazione può essere calcolata solo a condizione che il requester abbia inserito l’informazione “Risposta Corretta” (“Gold Answer”) in fase di creazione del task;
  • Riepilogo “Lavoratore”, viene mostrato lo score globale ottenuto dal lavoratore, il numero di campagne a cui ha partecipato e il numero delle risposte fornite. In aggiunta tali dati sono messi a confronto con quelli degli altri lavoratori iscritti al sistema.

Sicurezza e Permessi

All’interno del backend dell’applicazione Argo Plus, le operazioni eseguibili dagli utenti (requester o amministratori) e le pagine da loro consultabili sono gestite mediante un avanzato sistema di permessi sviluppato da Django e poi esteso secondo le necessità dell’applicazione. Il framework Django prevede l’esistenza per ogni modulo (o controller) della piattaforma di tre permessi distinti:

  • “Può aggiungere”, l’utente può inserire un nuovo elemento all’interno del sistema;
  • “Può modificare”, l’utente può modificare i valori di un elemento già esistente;
  • “Può eliminare”, l’utente può eliminare un elemento già esistente.

Durante lo sviluppo dell’applicazione si è deciso di aggiungere un nuovo livello di permessi (riassumibile in “può visualizzare”) in grado di garantire la visualizzazione degli elementi già inseriti senza però concedere i privilegi di inserimento, modifica o eliminazione. Tale permesso è ad esempio molto utile per permettere ai requester di conoscere la lista dei pattern e dei profile inseriti all’interno del sistema (senza poterne modificare o aggiungere di nuovi). All’interno dell’applicazione i permessi sono denominati semplicemente:

  • Can add;
  • Can view;
  • Can edit;
  • Can delete.

L’inserimento del nuovo permesso ha richiesto una profonda modifica del codice proposto da Django, questa modifica sarà discussa nel capitolo successivo. Di seguito sono riportati i permessi così come sono defniti all’interno della migration di installazione dell’applicazione.

MODULO PERMESSO REQUESTER ADMIN
Campagne View/Add/Edit/Delete Si/Si/Si/No Si/Si/Si/Si
Campagne – Worker View/Add/Edit/Delete Si/No/Si/No Si/Si/Si/Si
Task View/Add/Edit/Delete Si/Si/Si/Si Si/Si/Si/Si
Task – Risp. Possibili View/Add/Edit/Delete Si/Si/Si/Si Si/Si/Si/Si
Task – Setup View/Add/Edit/Delete Si/Si/Si/Si Si/Si/Si/Si
Task – Skill View/Add/Edit/Delete Si/Si/Si/Si Si/Si/Si/Si
Task – Worker View/Add/Edit/Delete Si/No/Si/No Si/Si/Si/Si
Sistema – Camp. Stati View/Add/Edit/Delete Si/No/No/No Si/Si/Si/Si
Sistema – Pattern View/Add/Edit/Delete No/No/No/No Si/Si/Si/Si
Sistema – Pattern/Setup View/Add/Edit/Delete Si/No/No/No Si/Si/Si/Si
Sistema – Profile View/Add/Edit/Delete No/No/No/No Si/Si/Si/Si
Sistema – Profile/Skill View/Add/Edit/Delete Si/No/No/No Si/Si/Si/Si
Sistema – Setup View/Add/Edit/Delete No/No/No/No Si/Si/Si/Si
Sistema – Skill View/Add/Edit/Delete No/No/No/No Si/Si/Si/Si
Sistema – Task Stati View/Add/Edit/Delete Si/No/No/No Si/Si/Si/Si
Sistema – Task Tipologia View/Add/Edit/Delete Si/No/No/No Si/Si/Si/Si
Worker View/Add/Edit/Delete No/No/No/No Si/Si/Si/Si
Django – User View/Add/Edit No/No/No Si/Si/Si
Django – Group View/Add/Edit No/No/No No/No/No

I moduli evidenziati, “Django – User” e “Django – Group” sono gli unici che fanno riferimento a dei model ereditati dal framework Django (generati durante la prima migration del sistema), pertanto essi non dispongono del permesso di sola lettura. Tale permesso non è comunque utile ai fini dell’applicazione.

Infine, è importante sottolineare come all’interno del sistema sia presente una particolare tipologia di utenti, detti “superuser” in possesso di permessi illimitati su tutti i moduli del sistema.