• Non ci sono risultati.

Configuratore ONEVision

N/A
N/A
Protected

Academic year: 2021

Condividi "Configuratore ONEVision"

Copied!
63
0
0

Testo completo

(1)

Studente/i

Gionas Bonardi

Relatore

Patrick Ceppi

Correlatore

-Committente

SUPSI ISIN

Corso di laurea

Ingegneria Informatica

Modulo

M00009 - Progetto di Diploma

Anno

2018/2019

Data

(2)
(3)

Indice

Abstract 1 Introduzione 3 1 Motivazione e contesto 5 1.1 Motivazione . . . 6 1.2 Contesto . . . 6 2 Problema 7 3 Tecnologie utilizzate 9 3.1 Back-end . . . 10 3.1.1 Spring Boot . . . 11 3.2 Front-end . . . 13 3.2.1 React . . . 14 3.2.2 Axios . . . 16

3.2.3 Dev Express (DX) React Grid . . . 17

3.2.4 React Bootstrap . . . 19 3.2.5 Redux . . . 20 3.2.6 React Redux . . . 23 4 Implementazione 27 4.1 Introduzione . . . 28 4.2 Back-end . . . 28 4.2.1 Schema . . . 28 4.2.2 Repositories . . . 29 4.2.3 Controllers . . . 30 4.3 Front-end . . . 31

4.3.1 Lo stato dell’applicazione - Redux . . . 32

4.3.2 Componente TrackPage . . . 35

4.3.2.1 Componente TrackList . . . 37

(4)

4.3.2.3 Componente TrackEdit . . . 40 4.3.2.4 InfoTab . . . 41 4.3.2.5 CamsTab e PointsTab . . . 42 4.3.2.6 CanvasTab . . . 44 4.3.3 Componente RacePage . . . 45 4.3.3.1 Componente RaceList . . . 46 4.3.3.2 Componente RaceCreate . . . 47

4.3.3.3 Componente RaceEdit e RaceDriversList . . . 49

4.3.3.4 Componente RaceDriverReplay . . . 51 4.3.3.5 Componente RaceBreadcrumb . . . 53 4.4 Componente Header . . . 53 5 Conclusione 55 5.1 Considerazioni personali . . . 55 5.2 Sviluppi Futuri . . . 55

(5)

Elenco delle figure

3.1 Esempio generico di risposta JSON in formato HAL . . . 11

3.2 Esempio entità con annotazioni JPA . . . 12

3.3 Esempio di Repository con Spring Data REST . . . 12

3.4 Esempio di componente in React con linguaggio JSX . . . 14

3.5 Esempio di componente con state in React . . . 15

3.6 Esempio di chiamata get con Axios . . . 16

3.7 Esempio di una griglia con DevExtreme React Grid . . . 17

3.8 Esempio del plug-in Search con DevExtreme React Grid . . . 18

3.9 Esempio di un bottone in Boostrap React . . . 19

3.10 Il flusso di Redux . . . 20

3.11 Esempio di Redux . . . 21

3.12 Esempio di React-Redux . . . 23

3.13 Esempio index.js react-redux . . . 24

3.14 Esempio component react-redux . . . 24

4.1 Schema DB . . . 28

4.2 Lista delle respositories . . . 29

4.3 Projections utilizzate . . . 30

4.4 Controllers utilizzati . . . 30

4.5 trackActions.js . . . 33

4.6 trackReducer.js . . . 34

4.7 Composizione del componente TrackPage . . . 35

4.8 Metodo render() di TrackPage . . . 36

4.9 Funzione di rendering della lista dei circuiti . . . 37

4.10 Pagina di creazione di un circuito . . . 38

4.11 Funzione di invio e configurazione form . . . 38

4.12 Pagina di modifica di un circuito . . . 40

4.13 Configurazione del form del componente InfoTab . . . 41

4.14 Tab per la configurazione delle telecamere . . . 42

(6)

4.16 Tab di visualizzazione della pista 2D . . . 44

4.17 Componente RacePage . . . 45

4.18 Componente RaceList . . . 46

4.19 Metodo TableRow . . . 46

4.20 Componente RaceCreate . . . 47

4.21 Configurazione del RaceForm . . . 47

4.22 Pagina di modifica di una gara . . . 49

4.23 Pagina per la gestione dei piloti di una gara . . . 49

4.24 Pagina per la visualizzazione del replay . . . 51

4.25 Costruttore del componente del replay della gara . . . 51

4.26 Esempio di Breadcrumb nella pagina replay . . . 53

(7)

Abstract

L’unione tra l’istituto SUPSI ISIN e l’azienda Internet.ONE ha l’obiettivo di creare una nuova versione del progetto denominato ONEVision che permette di registrare, in totale autono-mia, le performance automobilistiche tramite telecamere lungo i circuiti di autodromi italiani.

La gestione della pista e la configurazione delle telecamere viene effettuata dagli operatori percorrendo la pista e registrando i dati in modo manuale e senza il supporto di una piatta-forma specifica per questo scopo.

Il progetto di diploma svolto va a colmare la mancanza di un configuratore delle piste e delle gare per gli addetti ai lavori. Il sistema è composto da un interfaccia web e da un database dove salvare i dati. È possibile configurare la posizione delle telecamere, registrare i piloti alle gare e rivedere i replay su una mappa 2D del circuito.

The union between the SUPSI ISIN institute and the Internet.ONE company aims to create a new version of the project called ONEVision which allows the recording, in total autonomy, of automotive performance through cameras along the circuits of Italian racetracks.

The management of the track and the configuration of the cameras is carried out by the operators traveling along the track and recording the data manually and without the support of a specific platform for this purpose.

The diploma project carried out fills the lack of a track configurator and competitions for pro-fessionals. The system consists of a web interface and a database where to save the data. It is possible to configure the position of the cameras, register the riders at the races and review the replays on a 2D map of the circuit.

(8)
(9)

Introduzione

L’obbiettivo di questo documento è quello di esporre in maniera chiara e precisa quali sono stati gli obiettivi e le fasi che hanno contraddistinto lo sviluppo di questo progetto di diploma. Il rapporto descrive il problema che il progetto va a risolvere, le tecnologie utilizzate, l’imple-mentazione nonché i risultati ottenuti.

Il capitolo 1,motivazione e contesto, descrive il motivo per il quale si è svolta questa tesi

di Bachelor descrivendo lo scenario in cui si è andati ad operare.

Il capitolo 2, problema, descrive le problematiche che il progetto va a risolvere definendo

gli obiettivi ed i compiti svolti.

Il capitolo 3, tecnologie utilizzate, illustra e da un introduzione generale sulle tecnologie

utilizzate per lo sviluppo del lavoro, in modo da spigare i principi su cui si basano.

Il capitolo 4,implementazione, espone lo sviluppo completo che ha contraddistinto questo

progetto con spiegazioni tecniche e dettagliate.

(10)
(11)

Capitolo 1

(12)

1.1

Motivazione

Il progetto è stato sviluppato come tesi di Bachelor per il corso di laurea in Ingegneria Infor-matica svolto alla Scuola Universitaria della Svizzera Italiana (SUPSI) presso il Dipartimento di Tecnologie Innovative (DTI) situato a Manno. Al termine del percorso formativo, della du-rata di tre anni, si è chiamati a svolgere un progetto della dudu-rata di otto settimane. Questo progetto ha lo scopo di applicare tutte le conoscenze apprese durate l’arco formativo, di di-mostrare di essere in grado di applicare i concetti imparati e di documentare il tutto nonché di difendere il proprio lavoro davanti ad una commissione di docenti e di esperti del settore.

1.2

Contesto

La nuova versione di ONEVision è nata dalla collaborazione tra la SUPSI, più precisamente tra l’istituto ISIN [1] e l’azienda Internet.ONE [2]. L’ISIN è un istituto che svolge attività di insegnamento (laurea triennale, master e formazione continua) e attività di ricerca applicata nel settore delle tecnologie dell’informazione e della comunicazione. Internet.ONE è una società nata nel 1996 ed è orientata alla realizzazione di servizi Information and Communi-cations Technology (ICT).

ONEVision [3] è un sistema innovativo di ripresa automatizzato che consente molteplici applicazioni nel campo del Motorsport. La missione è quella di proporre un sistema di regia automatica in grado di seguire le azioni sulle piste automobilistiche e renderle disponibili in tempo reale agli utenti. L’unione tra SUPSI ISIN e Internet.ONE ha l’obiettivo di creare una nuova versione scalabile e con molteplici vantaggi tra i quali la non necessità di utilizzo di software di terze parti con relative licenze onerose e lo sviluppo di un sistema di computer vision che permetta alle telecamere di seguire i piloti in automatico.

(13)

Capitolo 2

(14)

La piattaforma ONEVision permette di rivedere le proprie performance automobilistiche re-gistrate in autodromi italiani. Tramite telecamere posizionate lungo le piste, è in grado, in totale autonomia, di creare per ogni pilota uno stream video personalizzato, disponibile in diretta su piattaforme social.

Attualmente la configurazione della pista e delle telecamere avviene in modo manuale. Gli operatori percorrono la pista con un auto ed ogni metro circa registrano sia la posizione GPS che quella della telecamera. La registrazione avviene con alcuni scripts, mediante comunicazioni via Whatsapp e senza il supporto di una piattaforma basata su un database correttamente modellizzato per tenere lo storico di quanto registrato.

Scopo del progetto è quello di creare un’applicazione web che permetta la configurazione del sistema agli addetti al lavoro. Composta principalmente da due parti: la configurazione dei circuiti e della posizione delle telecamere e dalla configurazione delle gare e delle auto che prederanno parte ad una gara/manifestazione.

Il progetto di diploma ha lo scopo di proporre una soluzione con un’interfaccia grafica e un database dove persistere i dati, in modo da dare un importante aiuto agli operatori che eseguono queste tipo di configurazioni.

(15)

Capitolo 3

(16)

3.1

Back-end

Per lo sviluppo della parte del back-end 1la scelta è ricaduta sul framework 2Spring Boot

[4] che permette di sviluppare, tramite linguaggio JAVA, un RESTful Web Service3. Mentre per quanto riguarda il database si è sceltoMySQL [5]. Avendo già una buona base appresa

durante i semestri di formazione la scelta è stata pressoché logica.

1

programma con il quale l’utente interagisce indirettamente.

2software progettato per supportare lo sviluppo di siti web dinamici, applicazioni web e servizi web. 3

(17)

3.1.1

Spring Boot

L’utilizzo di Spring Boot, più nello specifico il progetto Spring Data REST [6], permette di

semplificare e automatizzare lo sviluppo dei servizi RESTful/HATEOS4.

Figura 3.1: Esempio generico di risposta JSON in formato HAL

Gli endpoint generati automaticamente tramite Spring Data REST aderiscono a HATEOS, quindi si ha la necessità di rappresentare in un certo modo le risorse e i link seguendo dei requisiti specifici. Quello utilizzato dal framework è l’HAL (Hypertext Application Language), un esempio di risposta è mostrato nella figura 3.1. Spring Data REST analizza il modello di dominio dell’applicazione, quindi le entità Java, e genera gli endpoint 5 che rispondono alle richieste per ogni entità provvista di CRUD repository 6.

4

l’iterazione con il servizio web avviene esclusivamente tramite gli ipermedia forniti dal server.

5un indirizzo web a cui i clients di un servizio specifico possono accedervi. 6

(18)

Figura 3.2: Esempio entità con annotazioni JPA

Spring Data REST analizza il modello di dominio leggendo le annotazioniJPA7aggiunte alle classi JAVA, come mostrato in figura 3.2 e tramite le relative repository genera gli endpoint navigabili. In questo esempio viene trattato un utente con una chiave primaria e due campi: nome ed email.

Figura 3.3: Esempio di Repository con Spring Data REST

La configurazione della repository avviene estendendoPagingAndSortingRepository e impostando il percorso e il nome della risorsa, come mostrato nella prima riga di codice nell’immagine 3.3.

Navigando fino all’endpoint dell’utente, che in questo esempio è /users, si ottiene co-me risposta un file JSON 8 contenente la lista di tutti gli utenti presenti nel database.

Per fare in modo di ritornare i dati di uno specifico utente, si esegue una richiesta GET a/users/1, specificando un id. Questi endpoint sono provvisti anche di metodi POST, PATCH e DELETE come da standard RESTful/HATEOS.

7mappatura tra lo schema relazionale della base dati e le Entity. 8

(19)

3.2

Front-end

Tutta la gestione della parte di front-end 9 è stata implementata con la liberiaReact [7].

È stato utilizzato Axios [8] come gestore per le richieste HTTP e DX React Grid [9] per

la creazione di datagrid 10 modificabili. Per quanto riguarda la parte stilistica si è optato perReact Boostrap [10], che offre la possibilità di creare applicazioni web responsive11e permette di avere già alcuni componenti web preimpostati. Infine per la gestione dello stato dell’applicazione si è utilizzatoRedux.

9

area pubblicamente accessibile di un sito web o di una web application.

10controllo ricco di funzionalità per la visualizzazione di dati in forma tabellare. 11

(20)

3.2.1

React

React è una libreria Javascript open source12, sviluppata da Facebook, utilizzata per co-struire interfacce utente (UI).

Questa libreria permette di scrivere applicazioni in termini di componenti. Ogni componente corrisponde ad un elemento custom del DOM13, responsabile di renderizzare il contenuto dell’elemento e di gestirne gli eventi ad esso correlato. Un componente può essere inne-stato all’interno di un altro in modo da avere una gerarchia padre e figlio. Per la creazione dei componenti in React si consiglia l’uso di JSX che è una estensione della sintassi di Javascript.

Figura 3.4: Esempio di componente in React con linguaggio JSX

Nella figura 3.4, ShoppingList è un componente che rappresenta una lista della spesa. Per ogni componente è possibile specificare delle proprietà, chiamateprops. Alla riga 16 è presente un esempio di utilizzo di un componente, trattato come se fosse un elemento HTML14 alla quale viene aggiunto un attributo, una props,namecon valore Mark. Questo attributo/props è possibile usarlo nel metodorenderdel componente come si vede alla riga

12

software il cui codice sorgente è rilasciato con una licenza che lo rende modificabile o migliorabile da parte di chiunque.

13è una forma di rappresentazione dei documenti strutturati come modello orientato agli oggetti. 14

(21)

5.

Ogni componente è dotato di un metodo render()che al suo interno contiene la descri-zione di ciò che si desidera mostrare a schermo. React elabora questa descridescri-zione e ne visualizza il risultato.

Figura 3.5: Esempio di componente con state in React

Come mostra la figura 3.5, ogni componente può avere un suo stato privato. Questo stato è un oggetto Javascript che può contenere qualsiasi cosa. Per impostare uno stato iniziale di un componente bisogna appoggiarsi al metodoconstructor. Lo stato di un componente è possibile alterarlo solo utilizzando il metodothis.setStatementre per leggerlo e accede-re agli elementi si usathis.state.nomeElemento.

Altri metodi da segnalare sono:

• componentDidMount(), chiamato la prima volta che il componente viene costruito.

• componentDidUpdate(), chiamato ogni volta che avviene un cambiamento di stato

(22)

3.2.2

Axios

Axios è una libreria Javascript che permette di eseguire richieste HTTP. Funziona sia lato browser che lato server. Questa libreria è basata sullepromisedi Javascript e questo consente di scrivere codice async/wait per eseguire le richieste HTTP CRUD.

Figura 3.6: Esempio di chiamata get con Axios

La richiesta GET mostrata nell’immagine 3.6 viene gestita tramite i vari metodi:then,catch

e finally. Il primo è richiamato se la richiesta ha esito positivo mentre il secondo se avviene un errore. L’ultimo metodo è una porzione di codice che viene sempre eseguito sia in caso di successo che in caso di errore.

(23)

3.2.3

Dev Express (DX) React Grid

Il componente DevExtreme React Grid permette di visualizzare i dati in tabella e di esegui-re alcune operazioni tra cui modifica, ricerca e filtraggio. Questo componente permette di utilizzare una griglia in un’applicazione React normale o basata su Redux. Ha un’architet-tura componibile ed estendibile basata su plug-in e fornita con la piena compatibilità con Bootstrap.

Figura 3.7: Esempio di una griglia con DevExtreme React Grid

L’immagine 3.7 mostra una configurazione di base per la generazione di una griglia. Per impostare la tabella si deve definire nel tagGrid, come mostrato alla riga 25 e 26, le due proprietàrowsecolumnsche permettono di impostare le righe e le colonne. Inoltre biso-gna importare i plug-inTable eTableHeaderRow, presenti alla riga 28 e 29. Il primo ha il compito di renderizzare la tabella mentre il secondo renderizza l’intestazione della stessa.

(24)

Figura 3.8: Esempio del plug-in Search con DevExtreme React Grid

Un esempio di funzionalità che è possibile attivare è quella che permette la ricerca nei campi. Per abilitare questa funzionalità bisogna configurare quattro plug-ing. Il primo è il

SearchStateche permette di controllare lo stato della ricerca ed è visibile alla riga 6. Il se-condo è l’IntegratedFilteringche permette di eseguire la ricerca vera e propria e filtrare i dati della tabella. La riga 10 mostra laToolbar, che permette di renderizzare una conte-nitore sopra all’intestazione della tabella nella quale verrà inserito, tramiteSearchPanel, la barra di ricerca.

(25)

3.2.4

React Bootstrap

React-Bootstrap è una re-implementazione completa dei componenti Bootstrap usando React. Non ha alcuna dipendenza da bootstrap.js ojQuery. Se si installano React e React-Bootstrap si ha accesso a tutto quello di cui si ha bisogno per generare un applica-zione responsive.

Figura 3.9: Esempio di un bottone in Boostrap React

Come mostra l’esempio nell’immagine 3.9, un bottone in Bootstrap trattato come un compo-nente ha soltanto una propsvariantimpostata aprimaryche genera un bottone con sfon-do blu e testo bianco. Mentre con Bootstrap normale bisogna impostare altre informazioni nella classe CSS, comebtno l’attributo HTMLtype. Come si può vedere, React Bootstrap salva un po’ di battitura incapsulando le specifiche Bootstrap in componenti riutilizzabili, semplificando la navigazione attraverso il codice.

(26)

3.2.5

Redux

Redux è una libreria JavaScript open source per la gestione dello stato dell’applicazione che è l’insieme delle informazioni che determinano l’output in corrispondenza di un dato input in uno specifico istante.

Le Single Page Application in Javascript, come quella sviluppata in questo progetto, devono gestire molte informazioni tra cui:

• dati provenienti dal server;

• dati generati dall’applicazione ed inviati al server;

• dati che devono rimanere in locale in modo da rappresentare ad esempio la situazione corrente dell’interfaccia grafica.

Tutti questi dati rappresentano lo stato dell’applicazione e la gestione di esso diventa molto complessa per il fatto che questi dati variano per cause diverse come ad esempio l’intera-zione con l’utente o le interazioni con il server.

Alla sua base c’è la volontà di avere un unico stato, rappresentato da un oggetto JSON, e conservato in uno store. Lo stato può essere modificato solo in seguito ad azioni, la modifica vera e propria avviene tramite l’invocazione di una funzione chiamatareducer.

In un applicazione che fa uso di Redux si possono distinguere tre componenti principali:

Action , Reducer e Store.

Figura 3.10: Il flusso di Redux

Lo State rappresenta lo stato dell’applicazione rappresentato da un oggetto. Lo Store è

(27)

normale funzione Javascript che ha come parametri lo stato corrente e un azione che re-stituisce lo stato successivo. Le Action sono oggetti Javascript in grado di cambiare lo

stato dell’applicazione. Sono l’unico modo per comunicare con loStore. Le Action devono

avere almeno una proprietàtypee possono avere anche unpayloadcontenente parame-tri di quella specifica azione. Le Action Creator sono funzioni che generano le azioni più

complesse in base a parametri di configurazione. IlDispatcher ha il compito di inviare una Action allo Store, quest’ultimo, tramite uno specifico Reducer, esegue una transizione di

stato prevista dal tipo diAction ricevuta.

Figura 3.11: Esempio di Redux

L’Action Creator è una funzione che genera una azione. Nell’esempio mostrato

nell’im-magine 3.11 viene generata un azione che permette di creare, in questo caso, una policy. Come visto in precedenza, quest’azione ha un campotypee unpayloadper contenere le informazioni che aggiorneranno lo stato.

Il Reducer, situato alla riga 13, riceve come parametri lo stato attuale, in questo caso la

lista delle policy, e un azione. Il suo compito è di ricevere un azione e, in base al tipo, creare un nuovo stato cambiando quello già esistente. Alla riga 25, vengono combinati tra di loro e alla riga 30 assegnati alloStore. Lo stato iniziale viene creato richiamando tutti i Reducer

(28)

UnaAction viene generata alla riga 33 e viene eseguita tramite il Dispatcher e ricevuta

dalloStore, il quale, usando un opportuno Reducer, effettua la transizione di stato prevista

dal tipo diAction passata. In questo caso verrà aggiornato lo Store aggiungendo una

(29)

3.2.6

React Redux

La libreriareact-reduxpermette di usare in modo ufficiale Redux in un progetto in React. Questa libreria è gestita dal team di Redux e aggiornata con le ultime API di Redux e React.

Figura 3.12: Esempio di React-Redux

Nell’esempio mostrato in figura 3.12 è raffigurato il funzionamento di un’applicazione che gestisce una lista di libri e permette di selezionarne uno di essi. NelloStore vengono

im-magazzinati tutti iReducers e lo stato dell’applicazione. In react-redux vengono introdotti

inoltre due componenti:Provider e Connect.

Il Provider riceve come props lo Store. Questo componente ingloba tutta l’applicazione

intera, infatti deve essere inserita prima di tutti nella gerarchia dei componenti. Nella figura 3.12 è presente un componenteBookList che mostra a schermo la lista dei libri, ricevu-ta dallo Store, questo avviene tramite il componente Connect. Il componenete Connect

viene informato dalProvider se ci sono cambiamenti di stato. Se ce ne dovessero essere

il Provider manda il nuovo stato al Connect che poi lo da al componente BookListche aggiornare la UI.

IlConnect inoltre manda le Action eseguite nel componente direttamente al Provider che

smisterà il tutto allo Store e quindi ai Reducers. Ogni qualvolta ci dovesse essere un

aggiornamento dello stato, ilConnect informerà il componente passandoli lo stato nuovo e

(30)

Figura 3.13: Esempio index.js react-redux

Nella figura 3.13 si può notare il fileindex.js, il punto di partenza di un applicazione React. IlProvider, come detto nella sezione di Redux, ingloba l’intera applicazione. I Reducers

sono raccolti tutti in un file esterno e passati alla funzionecreateStore. Questi vengono richiamati tutti una prima volta con delle azioni vuote per generare lo stato iniziale.

Figura 3.14: Esempio component react-redux

Il componenteBookList, mostrato nell’immagine 3.14, è incapsulato dentro il componente

connect, come è possibile vedere alla riga 27. Questo componente ha 2 argomenti:

mapStateToProps, chiamato ogni volta che cambia lo stato. Riceve l’intero stato e

(31)

caso la lista dei libri.

mapDispatchToProps, questo parametro contiene le Action Creators, che vengono

trasformate in funzioni utilizzabili dal componente che invieranno automaticamente le azioni quando vengono richiamate. Alla riga 12 c’è un esempio di una chiamata a questeAction.

(32)
(33)

Capitolo 4

(34)

4.1

Introduzione

Il progetto è stato sviluppato su due repository differenti, uno per il back-end e uno per il front-end. Al momento della consegna le repository sono situate su GitLab. Il codice è commentato, in lingua inglese, la dove ci sono stati meccanismi da spiegare. Alcuni test dei componenti sono stati eseguiti per mostrare il loro funzionamento e per lasciare una traccia di come effettuarli. Ogni settimana ci sono stati incontri con il relatore per determinare obiet-tivi per le settimane successive e per aggiornarsi sullo stato dello sviluppo. Sulla piattaforma GitLab sono state utilizzate le issues che rappresentavano le cose da fare.

4.2

Back-end

4.2.1

Schema

Figura 4.1: Schema DB

Le tabelle con l’intestazione di colore blu rappresentano tutto quello che riguarda il circuito:

Track, è la pista vera e propria e ha come informazioni il nome, il punto di partenza e

lo spazio tra i vari punti geografici.

TrackData, sono tutti i punti, in ordine di posizione, che formano la pista con

(35)

Cam, sono tutte le telecamere presenti sulla pista con nome, latitudine, longitudine, il

punto di inizio e di fine della copertura della camera.

Le tabelle con l’intestazione di colore viola rappresentano tutto quello che riguarda la gara:

Race, è la gara e ha come informazioni il nome, la data di inizio e la data di fine.

Driver, sono tutti i piloti presenti nel sistema.

RaceDriver, sono i piloti che partecipano ad una determinata gara con l’aggiunta

riguardante il colore dell’auto.

L’ultima tabella,CarData, riguarda la raccolta dei punti sul circuito percorsi dal pilota in una

gara con l’informazione sulla data e ora.

4.2.2

Repositories

Figura 4.2: Lista delle respositories

Per ogni modello, visto in precedenza, è presente una repository gestita con Spring Da-ta Rest, come mostrato in figura 4.2. Queste repositories, come spiegato già nel capitolo dedicato a Spring Boot sottosezione 3.1.1, abilitano la possibilità di eseguire le richieste RESTful e quindi permettono di aggiungere, modificare ed eliminare elementi dal database.

Grazie a Spring Data Rest si ha la possibilità, con poco codice, di avere degli endpoint che permettono di eseguire le operazioni CRUD. Il metodo GET permette di ricevere in auto-matico i campi dei modelli. In due di queste, RaceDriverRepositoryeRaceRepository, però si è avuta la necessità di modificare la loro struttura. La modifica è possibile tramite le

Projections.

Come si nota nella figura 4.3, la prima projection va a modificare gli attributi di ritorno del modello RaceDriver, in quanto, di default, non vengono mostrati i campi di tipo chiave

esterna. Alla riga 5 e 6 sono presenti i metodi getter per recuperare questi campi e nello specifico l’oggetto pista e l’oggetto pilota. Mentre la seconda projection modifica il formato di ritorno della data, come si può vedere alla riga 13 e 15, e il campo chiave esterna pista, alla riga 17.

(36)

Figura 4.3: Projections utilizzate

4.2.3

Controllers

Figura 4.4: Controllers utilizzati

Nell’immagine 4.4 sono mostrati solo le intestazioni dei due controllers. Questi permetto il caricamento da file dei dati della pista, con punti annessi, e il caricamento delle telecamere. Il primo crea la pista con i punti mentre il secondo carica le telecamere di una pista specifi-cata. Una volta caricati i file vengono mappati e, se il formato è stato rispettato, inseriti nel database.

Questi controllers sono utili per offrire la possibilità agli operatori, quando devono inserire una nuova pista, in quanto fanno un giro di pista con un auto ed ogni metro ca. prendono sia la posizione GPS che la posizione delle telecamere.

(37)

4.3

Front-end

L’applicazione front-end è un Single Page Application che è suddivisa in due componenti principali: quella riguardante i circuiti e quella delle gare.

Nel componente di gestione dei circuiti, accessibile da un menu posto in alto, è possibile ac-cedere a una sezione dove si può configurare tutto quel che riguarda la pista partendo dalle nome, passando dalle telecamere e infine dai punti geografici. I punti geografici permetto-no la generazione di una mappa 2D dove è possibile vedere la posizione delle telecamere lungo il circuito.

La sezione che invece gestisce le gare permette la creazione di una di essa, di iscrivere un pilota ad una gara e di vedere il suo replay in una comoda mappa 2D.

(38)

4.3.1

Lo stato dell’applicazione - Redux

In questo progetto viene usato Redux in modo da avere uno stato globale per la gestione delle informazioni proveniente dal database, per la spiegazione generale del suo utilizzo fare riferimento al capitolo dedicato a Redux sottosezione 3.2.5.

Gli Action Creators sono tutti raggruppati in una cartella denominata actions, stesso di-scorso per i Reducers raccolti nella cartellareducers.

Lo stato di Redux contiene sette liste:

tracksList, contenente tutti i circuiti

camsList, contenente le camere di un specifico circuito

pointsList, contenente i punti appartenenti ad una pista

racesList, contenente tutte le gare

raceDriversList, contenente tutti i piloti di uno specifica gara

driversList, contenente tutti i piloti presenti nel sistema

carDatasList, contenente tutti i punti di un pilota che ha percorso durante la gara

Questi oggetti sono tutti composti da un campo lista, che contiene l’informazione vera e propria, e da un campo errore nel caso ci dovesse essere un possibile problema nell’e-laborare le informazioni o nella modifica di esse. Quindi, ad esempio, per accedere al-la lista dei circuiti si richiama tracksList.tracks mentre per accedere all’errore si usa

tracksList.error.

Per spiegarne il funzionamento si prenda in considerazione la gestione della lista dei circuiti che, simile alle altre, ha principalmente 4 Actions:

fetchTracks(), recupera tutti i circuiti, in formato JSON, dall’endpoint /tracks con metodo GET.

createTrack(objectValues), crea una pista e la aggiunge nel database, tramite

l’end-point/trackscon metodo POST.

editTrack(id, objectValues), modifica una pista, tramite l’endpoint/tracks/idcon metodo PATCH.

deleteTrack(id), elimina una pista, tramite l’endpoint/tracks/idcon metodo DELE-TE.

(39)

Figura 4.5: trackActions.js

Come è possibile vedere dalla figura 4.5, ogni Action Creator è costruita con un altro Action Creator che in questo caso si chiama actionBuilder. L’actionBilder si aspetta come parametri il metodo HTTP della richiesta che si vuole eseguire, l’endpoint a cui puntare, il tipo di azione generata se tutto va bene, un’altra tipo di azione se dovesse succedere un errore e una callback se si ha la necessità eseguire qualcosa al termine dell’esecuzione.

Si prenda come riferimento l’Action CreatorfetchTracks, se la chiamata all’endpoint/tracks

va a buon fine, viene generata un azione con campotypeFETCH_TRACKS e nel campo

(40)

Figura 4.6: trackReducer.js

Il Reducer che si occupa dello stato della pista, mostrato nell’immagine 4.6, riceve l’azio-ne e in base al tipo esegue le modifiche allo stato. In questo caso l’aziol’azio-ne ricevuta è FETCH_TRACKS, quindi il nuovo stato avrà la pista ricevuta dal web server e il campo errore impostato anull. Se invece l’azione ricevuta dovesse essere ERROR_TRACK, lo stato avrà una lista vuota e il campo errore con il testo ritornato dall’action.

Alcuni Action Creator non sono costruiti con l’actionBuilder perché implementate in modo differente tra i qualifetchPoints efetchCams. L’azione che crea e modifica le piste uti-lizza l’endpoint /races, questo come visto in precedenza usa delle projections, quindi una volta creato o modificato una pista si richiama la projection che ritorna il formato corretto

(41)

4.3.2

Componente TrackPage

Figura 4.7: Composizione del componente TrackPage

Il componenteTrackPagecontiene tutte le funzionalità che permettono la creazione, la mo-difica e l’eliminazione di tutto quel che riguarda un circuito. È composto da altri piccoli componenti innestati, ognuno con uno scopo ben preciso tra cui la lista dei circuiti, il com-ponente per creare una nuova pista e per editarne una già presente all’interno del database.

Come mostra la figura 4.7 il componente principale contiene al suo interno altri componenti tra cui:

• TrackList, sempre visibile a sinistra e mostra la lista dei circuiti.

• TrackCreate, navigabile premendo il bottone in fondo alla lista, ’aggiungi’ e permette di creare un circuito.

• TrackEdit, navigabile premendo una qualsiasi circuito nella lista e ne permette la modifica.

QuandoTrackPageviene caricato, avviene una chiamata all’Action CreatorfetchTracks(), che come accennato nel capitolo dedicato allo stato dell’applicazione sottosezione 3.2.5, è responsabile di recuperare la lista dei circuiti presenti nel database. Viene inoltre montato anche il componenteTrackListche visualizza la lista a schermo.

(42)

Figura 4.8: Metodo render() di TrackPage

Se l’action creator fallisse nel ritornare la lista, il componente mostrerebbe un errore tramite unAlert, come si vede in figura 4.8 alla riga 4. TrackPage è composta da due colonne, la prima colonna contiene un componente figlioTrackListmentre la seconda contiene un elementoSwitchche permette di caricare i componenti a dipendenza dell’URL:

• /circuiti/nuovocarica il componente per la creazione di un nuovo circuito.

• /circuiti/idcarica il componente per la modifica di un circuito già presente in base all’id nell’URL.

Il metodorender()permette di caricare qualsiasi elemento a schermo l’importante è che sia tutto racchiuso in un unico tag. Per questo problema ci viene in autoReact.Fragment

(43)

4.3.2.1 Componente TrackList

Figura 4.9: Funzione di rendering della lista dei circuiti

La lista dei circuiti, che è sempre visibile sulla sinistra, è renderizzata dal componente

TrackList. Esso reperisce la lista dallo stato di Redux, caricata precedentemente dal componente padre, la ordina e aggiunge il collegamento ad ogni elemento per navigare alla pagina di modifica, come mostrato in figura 4.9.

Il componente LinkContainer permette, oltre che impostare un percorso navigabile, di includere un sotto elemento. In questo caso è un Item che rappresenta un elemento

Bootstrap. In fondo alla lista è presente un bottone che permette di accedere alla pagina di creazione di un circuito: componenteTrackCreate.

(44)

4.3.2.2 Componente TrackCreate

Figura 4.10: Pagina di creazione di un circuito

Il componenteTrackCratepermette di creare un circuito. La creazione di un circuito avvie-ne in due modi: il primo tramite un form per inserire i valori mentre il secondo permette di caricare un file JSON contenente le informazioni della pista e dei suoi punti geografici.

L’inserimento tramite il form, avviene attraverso un altro componente, chiamatoTrackForm, che utilizza la libreriaredux-form. Questo componente è utilizzato sia per permette la fase di inserimento che la fase di modifica nel componenteTrackEdit.

Figura 4.11: Funzione di invio e configurazione form

Come mostra la figura 4.11, la funzione di invio dei dati avviene tramite un’Action Creator per la creazione della pista. Questa funzione viene passata poi alTrackFormsotto forma di

props.

La gestione delle fasi del caricamento del file avviene tramite lo stato del componente. Gli stati possibili sono quattro:

(45)

EMPTY: quando il file non è ancora stato scelto.

LOADING: quando il file è stato scelto ed è stato premuto invio.

OK: quando il file è stato caricato con successo e il circuito è stato creato.

ERORR: quando il file caricato non è conforme al formato richiesto.

La funzione che carica il file, dal nome onSubmitFile, carica il file nel database per poi essere processato, utilizzando l’endpoint/uploadTrackWithPoints. Il controller che gesti-sce la richiesta è situato nella classeUploadControllere hai il nome diuploadTrackWithPoints.

(46)

4.3.2.3 Componente TrackEdit

Figura 4.12: Pagina di modifica di un circuito

Il componenteTrackEditpermette la modifica di un circuito. Il componente è suddiviso da 5 tab che rappresentano 5 componenti:

Info: tab che contiene il componenteInfoTabe permette la modifica del circuito.

Telecamere: tab che contiene il componenteCamsTabe permette l’aggiunta, la modi-fica e l’eliminazione delle telecamere.

Punti: tab che contiene il componentePointsTabe permette l’aggiunta, la modifica e l’eliminazione dei punti geografici della pista.

Circuito: tab che contiene il componenteCanvasTabe permette di visualizzare il cir-cuito in 2D con la posizione delle telecamere.

Alla sua costruzione e al suo aggiornamento, quindi tramite le due funzioni base di React

componentDidMountecomponentDidUpdate, vengono chiamati due action creator che si

occupano di recuperare i punti e le telecamere della pista selezionata. Durante il recupero di queste informazioni viene visualizzato a schermo una rotellina di caricamento. Da segnalare che quando si passa da una pista all’altra selezionandole dalla lista, il componente non viene distrutto e ricreato bensì aggiorna soltanto le props, quindi si passa solo dalla funzione

componentDidUpdate. Per gestire ciò il componente utilizza due stati interni:

fetchFinished: questo stato permette di sapere quando le funzioni asincrone che

recuperano i punti e le camere hanno finito di ritornare i dati.

(47)

4.3.2.4 InfoTab

Figura 4.13: Configurazione del form del componente InfoTab

Il compito di questo componente è di permettere la modifica dei tre campi di un circui-to: nome, startIndex e spacing. Come per il TrackCreatequesto componente fa uso del

TrackForm. Come è possibile vedere dall’immagine 4.13, vengono passate quattro props:

title: che permette di passare il nome della pista.

initialValues: che permette di riempire i tre campi con i valori che ha la pista.

onSubmit: l’action creator da eseguire quando si aggiorna la pista tramite il bottone

’salva’.

onDelete: l’action creator da eseguire quando si elimina la pista tramite il bottone

(48)

4.3.2.5 CamsTab e PointsTab

Figura 4.14: Tab per la configurazione delle telecamere

Il componente per la configurazione delle telecamere si basa su una tabella di DX React Grid. Come spiegato nel capitolo dedicato sottosezione 3.2.3, questo componente permet-te di visualizzare e modificare i dati in una comoda tabella. Esistono due modi per inserire le telecamere: uno da file tramite un file JSON e l’altro manualmente. Come si vede in figura 4.14, in alto è situato il bottone per il caricamento da file che utilizza il metodoonSubmitFile

mentre per inserire una telecamere manualmente si può premere sul pulsante ’new’ posi-zionato a sinistra nell’intestazione della tabella.

La tabella mostra le colonne nome, altitudine, longitudine, startIndex e endIndex. Tutte queste colonne sono modificabili tramite il bottone ’edit’ ed è possibile eliminare una camera usando il bottone ’delete’.

Figura 4.15: Metodo che gestisce gli eventi nella tabella

Nella figura 4.15 è mostrato il metodo del componente che gestisce gli eventi della tabella. Quando riceve l’eventoaddedaggiunge ai campi inseriti dall’utente anche la chiave esterna

(49)

che in questo caso è la pista. Una volta aggiunto questo campo viene eseguito l’action creatoraddCamche aggiunge la camera alla pista nel database e aggiorna lo stato. Quando si elimina una pista si esegue l’action creatordeleteCampassandoli l’id delle camera da eli-minare. Per la modifica, viene recuperato l’id della camera modificata e poi viene chiamato

editCamche modifica la telecamera nel database e aggiorna lo stato.

Se ci dovesse essere un qualsiasi tipo di problema, ad esempio l’aggiunta di testo in un campo di solo numeri, viene mostrato un errore per due secondi. Questo errore, situato nel-l’oggettocamsListnello stato di Redux, viene azzerato dopo due secondi tramite l’action:

clearErrorCam.

PointsTab è simile a CamsTab, gli unici elementi che cambiano sono alcuni plug-in e le

colonne mostrate nella tabella. Inoltre non è presente un bottone per caricare un file JSON con i punti.

(50)

4.3.2.6 CanvasTab

Figura 4.16: Tab di visualizzazione della pista 2D

Tramite le telecamere e i punti configurati nei tab visti in precedenza, è possibile visualiz-zare, in formato 2D, la pista con le posizioni delle telecamere e del punto di partenza. Il componente recupera, dallo stato dell’applicazione, punti e telecamere che vengono mani-polate in un canvas e mostrare a schermo.

Questo canvas è stato sviluppato e adeguato includendo un prototipo già esistente. Quan-do si ridimensiona la finestra e quindi si aggiorna il componente è stato utilizzato il metoQuan-do

debouncedella libreria lodashche permette di eseguire meno eventi di quelli che si ge-nerano. Questo permette di avere un ridimensionamento più fluido e avere i dati sempre caricati in modo corretto.

(51)

4.3.3

Componente RacePage

Figura 4.17: Componente RacePage

Questo componente permette di gestire la parte riguardante le gare sui circuiti. Come è pos-sibile vedere dall’immagine 4.17TrackPagegestisce il routing tra i componenti relativi alle gare. Quando viene caricato e si ha impostato l’URL/garedi default viene mostrato il com-ponenteRaceList. Se si naviga su/gare/:idviene caricato il componenteRaceEdit do-ve è possibile modificare i dati della pista selezionata tramite l’id. Nell’endpoint /gare/new

viene caricato il componente che permette di creare una gara. Il primo percorso, invece, passandoli due parametriideidRaceDrivercarica il componente che mostra il replay del pilota di una gara selezionata.

Nel metodo componentDidMount() sono situate le chiamate per recuperare le piste e le gare dal database e quindi dallo stato di Redux.

(52)

4.3.3.1 Componente RaceList

Figura 4.18: Componente RaceList

RaceListè composto da una DX React Grid che mostra, in una tabella, tutte le gare. Que-sta tabella ha il plug-in che permette di riordinare le colonne premendo sul nome nell’inte-stazione e un altro che abilita la possibilità di ricercare una gara in qualsiasi campo della tabella. Premendo su una gara si accede alla pagina che permette la modifica della gara e dei suoi piloti,RaceEdit. Mentre il tasto aggiungi in alto a sinistra permette di caricare il componenteRaceCreateper la creazione di una gara.

Figura 4.19: Metodo TableRow

Come si vede in figura 4.19, il metodo TableRow va a modificare le righe generate nella tabella impostato un evento sul click della gara. L’elementohistorypermette di navigare fino al componente di modifica della gara selezionata.

(53)

4.3.3.2 Componente RaceCreate

Figura 4.20: Componente RaceCreate

Questo componente utilizza, come visto in precedenza, un redux-form nello specifico un componenteRaceForm. Nel form è possibile inserire il nome della gara, impostare la data di inizio e di fine e selezionare da una lista il circuito su cui si svolge la gara. In alto è presente un componenteRaceBreadcrumbche permette di navigare tra le pagine.

Figura 4.21: Configurazione del RaceForm

Nell’immagine 4.21 viene mostrato la configurazione delRaceFormper il componenteRaceCreate. Sono presenti quattro props:

title: che permette di passare il nome della gara.

initialValues: che permette di riempire i quattro campi con i valori che ha la gara.

(54)

onSubmit: l’action creator da eseguire quando si crea una gara. In questo caso viene

(55)

4.3.3.3 Componente RaceEdit e RaceDriversList

Figura 4.22: Pagina di modifica di una gara

Questo componente permette la modifica delle gare e la gestione dei piloti. La visualizzazio-ne è gestita tramite i tab di Bootstrap: uno mostra il compovisualizzazio-nenteRaceForme l’altro mostra

RaceDriversList. Il RaceForm è configurato passandoli alla propsinitialValuesla pi-sta selezionata e recuperata dallo pi-stato di Redux. Alle propsonSubmiteonDelete, legati ai rispettivi bottoni "Salva" ed "Elimina", sono assegnati le action:editRaceedeleteRace.

Figura 4.23: Pagina per la gestione dei piloti di una gara

Il componente RaceDriversListpermette di visualizzare e modificare i piloti tramite una DX React Grid, come mostrato in figura 4.23. Alla costruzione del componente carica tra-mite l’actionfetchRaceDriverse passandoli l’id della gara, i piloti appartenenti alla corsa.

(56)

Il tasto ’edit’ permette soltanto la modifica del campo "Colore Auto". Si ha la possibilità di creare e aggiungere i piloti tramite il bottone in alto a sinistra, ’Aggiungi Piloti’, che carica il componenteDriversListModal. Componente con la funzione specifica di permettere l’aggiunta dei piloti e la creazione di essi sempre tramite una DX React Grid, in questo com-ponente viene fatto un filtro nella lista per non mostrare i piloti già iscritti.

Le riga contenute nella griglia, che mostrano i piloti iscritti ad una gara, sono modificate per permettere di premere su un pilota e di accedere al componente per la visualizzazione del replay della gara:RaceDriverReplay.

(57)

4.3.3.4 Componente RaceDriverReplay

Figura 4.24: Pagina per la visualizzazione del replay

Grazie a questo componente si ha la possibilità di vedere il replay di una gara. Tramite i pulsanti avanti, indietro e play si può gestire l’animazione del pallino verde che simula l’auto in pista. Al caricamento di questo componente vengono richiamate tre action, oltre a quella per caricare i piloti e selezionare quello desiderato:

• fetchCams, che carica le telecamere della pista.

• fetchPoints, che carica i punti geografici per il disegno della pista.

• fetchCarDatas, che caricano i punti percorsi dal pilota sulla pista.

Figura 4.25: Costruttore del componente del replay della gara

Per gestire il pallino verde e simularne il movimento, nello stato del componente vengono usati le variabiliinPause eindex. I CarData, che sono i punti percorsi dal pilota con

(58)

re-lativa data e ora salvati in un array, vengono percorsi tramite la variabileindex che viene incrementata ogni 20ms dalla funzionemoveCarDataTimeout. La variabileinPause serve a gestire quando viene premuto il pulsante play e stop così da far andare avanti o meno l’animazione.

(59)

4.3.3.5 Componente RaceBreadcrumb

Figura 4.26: Esempio di Breadcrumb nella pagina replay

Questo componente permette di navigare tra le pagine delle gare e avere sempre sott’oc-chio in che pagina si è situati. Il RaceBreadcrumb è utilizzato in tutti i componenti legati alle gare e in base alle props passate da questi componenti si riesce a gestire le differen-ti visualizzazioni, tra i quali mostrare la posizione attuale e i link per tornare alla pagina precedente.

4.4

Componente Header

Figura 4.27: Header

Il componente Headerè sempre visibile in cima e permette di navigare tra le due pagine principali: circuiti e gare. Quando si ridimensiona la finestra e si arriva ad una certa dimen-sione, quella di un dispositivo mobile, i due link diventano il classico menu ad hamburger che si trovano sui siti responsive.

(60)
(61)

Capitolo 5

Conclusione

Il problema principale da risolvere era quello relativo alla configurazione della pista in quanto gli addetti ai lavori non avevano un supporto adeguato per registrare i dati della pista e delle relative gare/eventi.

Il sistema sviluppato permette ai collaboratori di inserire i dati delle piste e delle telecamere in modo semplice e immediato. La possibilità di vedere la pista in 2D generata in automatico tramite questi dati permette la correzione immediata di problemi laddove ce ne fossero. La pagina dei circuiti permette di configurare tutto quel che riguarda le piste quindi nome, telecamere e punti geografici. La pagina delle gare permette la creazione di competizioni aggiungendo piloti e permettendo di visualizzare il replay delle prestazioni sulle mappe 2D.

5.1

Considerazioni personali

Lo sviluppo di questo progetto mi ha permesso di potere lavorare a stretto contatto con nuove tecnologie e coniugare conoscenze già apprese con quelle più recenti. Ho scelto di utilizzare React in modo da poterlo imparare e capire i suoi meccanismi, questo mi ha permesso di arricchire il mio bagaglio tecnico. Il progetto è stato molto interessante e sti-molante dato anche dal fatto che va a risolvere un problema reale. Il mio lavoro è stato facilitato dal mio relatore Patrick Ceppi che, grazie alla sua disponibilità e conoscenza, mi ha permesso di trovarmi sempre a mio agio e di riuscire negli obiettivi stabiliti.

5.2

Sviluppi Futuri

Una funzionalità introdotta in parte, ma che deve essere migliorata e supportata dal progetto principale, è la possibilità di vedere il video del replay frame per frame di una gara di un pilota. Tale funzione deve essere ancora implementata ma le basi per poter farla funzionare sono state posate.

(62)
(63)

Bibliografia

[1] Sito dell’istituto isin. http://www.supsi.ch/isin_en. [2] Sito internet.one. http://internetone.it.

[3] Sito onevision. http://onevision.social.

[4] Sito springboot. https://spring.io/projects/spring-boot. [5] Sito mysql. https://www.mysql.com.

[6] Sito spring data rest. https://spring.io/projects/spring-data-rest. [7] Sito react. https://reactjs.org.

[8] Sito axios. https://github.com/axios/axios.

[9] Sito dev express react grid. https://devexpress.github.io/

devextreme-reactive/react/grid/.

Riferimenti

Documenti correlati

b) scrivere nel campo [Testo da aggiungere] la parte di testo che si vuole aggiungere e nel campo [Testo da eliminare] la corrispondente parte di testo che

Prima di accedere al configuratore si aprirà una finestra in cui inserire il codice della tua  configurazione riferito alla personalizzazione che stai effettuando: es.

Siamo disposti ad essere inviati ovunque per testimoniare la nostra fede in Dio Padre misericordioso, per proclamare il Vangelo della salvezza di Gesù Cristo, per condividere la

Il configuratore degli appalti ha l’obiettivo di migliorare le capacità operative delle amministrazioni nella individuazione delle procedure selettive di affidamento,

Progetto ETICA pubblica nel Sud.. Napoli, 20

[r]

Dati un insieme A che contiene n elementi, un insieme B che contiene m elementi, ed una relazione R da A a B, la relazione R si può rappresentare con una matrice booleana nxm

Si consideri una lista di numeri interi Lista implementata come lista doppiamente puntata non circolare implementata utilizzando la seguente struttura.. struct