1
Fork 0
mirror of https://github.com/Steffo99/alexandria.git synced 2024-11-21 13:24:18 +00:00

Merge branch 'relazione'

This commit is contained in:
Steffo 2020-06-08 00:30:53 +02:00
commit 103ad3bfa0
Signed by: steffo
GPG key ID: 896A80F55F7C97F0
76 changed files with 3321 additions and 462 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
relazione.pdf eol=crlf

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.idea/

BIN
0-spec.pdf Normal file

Binary file not shown.

View file

@ -1,6 +1,6 @@
# Descrizione
Si vuole realizzare una base di dati a supporto di un sito web che permetta la creazione, gestione e condivisione della propria raccolta multimediale, come è possibile fare su altri siti web, quali [aNobii](https://www.anobii.com/), [MyAnimeList](https://myanimelist.net/) e [The Backloggery](https://backloggery.com/).
Si vuole realizzare una base di dati a supporto di un sito web che permetta la creazione, gestione e condivisione della propria libreria multimediale, come è possibile fare su altri siti web, quali [aNobii](https://www.anobii.com/), [MyAnimeList](https://myanimelist.net/) e [The Backloggery](https://backloggery.com/).
Il sito sarà suddiviso in sezioni, ciascuna riguardante un [media](https://it.wikipedia.org/wiki/Mezzo_di_comunicazione_di_massa) diverso:
@ -30,13 +30,14 @@ Gli utenti potranno aggiungere _elementi_ alla loro raccolta multimediale.
Un elemento rappresenta una copia di un libro, di un film o di un videogioco posseduta da un utente.
Ogni elemento avrà associato uno **stato** da una lista di opzioni diversa per ogni tipologia:
Ogni elemento avrà associato uno **stato** da una lista di opzioni diverse per ogni tipologia:
- Libro
- Da iniziare
- Iniziato
- Finito
- Abbandonato
- Non applicabile
- Film
- Da vedere
- Visto
@ -45,6 +46,7 @@ Ogni elemento avrà associato uno **stato** da una lista di opzioni diversa per
- Iniziato
- Finito
- Completato al 100%
- Non applicabile
Inoltre, ogni elemento avrà associata una **provenienza** da un'altra lista:
@ -70,8 +72,13 @@ Inoltre, ogni elemento avrà associata una **provenienza** da un'altra lista:
- Perso / Venduto / Restituito / Non più posseduto
- Altro
Un utente è in grado di creare una nuova pagina di un determinato elemento (se, ad esempio, ha letto un libro non ancora registrato nel database). Per fare ciò dovrà inserire obbligatoriamente il tipo di elemento, il suo dato chiave e il titolo dell'opera, mentre gli altri campi sono facoltativi: possono essere inseriti per completezza, oppure lasciati vuoti. Un utente può inoltre modificare una pagina già esistente al fine di aggiungervi informazioni o correggere errori.
Un amministratore è in grado di eliminare le pagine, in caso esse rappresentino elementi non realmente esistenti.
Un utente potrà creare un nuovo oggetto (edizione di libro, film...) di cui aggiungere poi un elemento nella sua libreria.
Per farlo dovrà selezionarne il tipo e inserirne la chiave (ISBN, EIDR...) e il titolo; tutti gli altri campi saranno facoltativi: possono essere compilati per completezza, oppure lasciati vuoti.
Un utente può inoltre modificare una pagina già esistente al fine di aggiungervi informazioni o correggere errori.
Un amministratore è in grado di eliminare le pagine, in caso esse rappresentino oggetti non realmente esistenti.
## Recensioni
@ -83,9 +90,7 @@ La media delle valutazioni delle recensioni relativa a un dato libro / film / se
Gli utenti potranno decidere in qualsiasi momento di eliminare una loro recensione.
Gli amministratori, oltre a poter decidere di eliminare recensioni, potranno marcarle come _nascoste_ nel caso le considerino inappropriate o non inerenti.
Le recensioni nascoste potranno apparire nel sito, ma avranno un aspetto diverso e il commento all'interno non sarà visibile a meno che l'utente non clicchi un tasto.
Gli amministratori potranno eliminare le recensioni nel caso queste violino i termini di servizio del sito web.
## Libri ed edizioni

43
2-glossario.md Normal file
View file

@ -0,0 +1,43 @@
# Glossario
Scritta la [descrizione](1-descrizione.md), si è realizzato un glossario al fine di identificare le parole chiave in essa contenute.
## Generale
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| `Utente` | username, hash della password, email, è amministratore, è bannato | user, admin, amministratore | possiede Elementi | |
| `Elemento` | stato, provenienza | | di una copia di un Libro / Film / Videogioco, posseduto da un Utente | |
| `Recensione` | valutazione (0-100), commento, data, è nascosto | valutazione, commento, post | riguardante un Elemento | |
## Libri
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| `Libro` | titolo originale, sinossi | testo, saggio, romanzo, opuscolo | scritto da uno o più Autori, appartenente a uno o più Generi, con più Edizioni (libro, audio), correlato ad altri Libri | |
| `Genere` | nome | | a cui appartengono i Libri | |
| `Edizione` (libro) | **isbn**, titolo localizzato, pagine, copertina | _Libro_ (ambiguo), pubblicazione, stampa | di un Libro, posseduta da più Utenti (_Elemento_), pubblicata da un Editore | |
| `Edizione` (audio) | **isbn**, titolo localizzato, durata, immagine | | di un Libro, posseduta da più Utenti (_Elemento_), pubblicata da un Editore, narrata da uno o più Narratori | |
| `Autore` | nome | scrittore | scrive dei Libri | |
| `Editore` | nome | | pubblica delle Edizioni (libro, audio) | |
| `Narratore` | nome | voce narrante | narra delle Edizioni (audio) | |
## Film
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| `Film` | **eidr**, titolo originale, sinossi, durata, locandina | pellicola | guardato da Utenti (_Elemento_), realizzato da Cast, prodotto da Studio, appartenente a Generi, scritto da Sceneggiatori, correlato ad altri Film | |
| `Genere` | nome | | a cui appartengono i Film | |
| `Cast` | nome | "attore", "regista", "scenografo", "produttore esecutivo" | Prende parte al Film, ha un Ruolo | I ruoli sono specificati nella tabella Ruolo |
| `Ruolo` | nome | | di Cast | Il ruolo è un attributo! |
| `Studio` | nome | azienda, casa produttrice | che ha prodotto un Film | |
| `Localizzazione` | titolo alternativo, lingua | titolo | relativo a un Film | |
## Giochi
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| `Gioco` | titolo, descrizione | videogioco, videogame | sviluppato da uno o più Studio, pubblicato da uno o più Studio, appartenente a Generi, con più Edizioni | |
| `Edizioni` | piattaforma, box art, titolo alternativo | | di un Gioco, giocata da Utenti (_Elemento_), portato da uno o più Studio | |
| `Generi` | nome | | a cui appartengono Giochi | |
| `Studio` | nome | | che ha sviluppato Giochi, che ha portato Edizioni | |

27
3-1-schema-scheletro.md Normal file
View file

@ -0,0 +1,27 @@
# Schema scheletro
Dal glossario, si è poi realizzato con il software [diagrams.net](https://www.diagrams.net/) uno schema scheletro della base di dati, contenente le principali entità e relazioni.
È allegato alla relazione il file [`3-1-schema-scheletro.drawio`](3-1-schema-scheletro.drawio) contenente l'intero schema scheletro in un formato modificabile; per comodità, si riportano qui sotto i suoi contenuti sotto forma di immagini.
## Legenda
I _quadrati_ rappresentano le **entità**, i _rombi_ rappresentano le **relazioni**, le _linee continue grigie_ rappresentano l'**appartenenza** di un'entità a una relazione e infine le _frecce blu_ rappresentano l'esistenza di una [**gerarchia IsA**](3-2-gerarchie.md) tra le entità connesse.
## Immagini
### Generale
![](img/3-1-schema-scheletro/generale.png)
### Libri
![](img/3-1-schema-scheletro/libri.png)
### Film
![](img/3-1-schema-scheletro/film.png)
### Giochi
![](img/3-1-schema-scheletro/giochi.png)

23
3-2-gerarchie.md Normal file
View file

@ -0,0 +1,23 @@
# Classificazione delle gerarchie
Nello schema scheletro di Alexandria compaiono **due gerarchie IsA**, rappresentate da frecce continue blu.
## Gerarchia degli `Elementi`
![](img/3-2-gerarchie/gerarchia-1.png)
Il tipo di dato alla base di Alexandria è l'`Elemento`.
Un `Elemento` rappresenta una aggiunta da parte di un utente alla propria libreria di un libro, film o videogioco.
Nella [descrizione](1-descrizione.md) si specifica che tutti gli `Elementi` devono avere uno _stato_ e una _provenienza_ specifici al tipo di `Elemento`; è quindi necessaria la distinzione dei vari tipi di `Elemento` e creando così una gerarchia **esclusiva** (un `Elemento` non può essere sia un libro sia un film allo stesso tempo).
Si è deciso di rendere **non totale** la gerarchia in modo da permettere l'introduzione di nuovi tipi di `Elementi` in futuro.
## Gerarchia delle `Edizioni`
![](img/3-2-gerarchie/gerarchia-2.png)
La [descrizione](1-descrizione.md) prevede che le `Edizioni` dei libri e degli audiolibri abbiano attributi diversi: i libri hanno il _numero di pagine_ e l'immagine della loro _copertina_, mentre gli audiolibri hanno la _durata_ e la _cover art_ ad essi associata.
Si viene a creare così una gerarchia **totale** (un'Edizione è o libro o audiolibro) ed **esclusiva** (una edizione non può essere sia libro sia audiolibro).

11
3-3-autoassociazioni.md Normal file
View file

@ -0,0 +1,11 @@
# Classificazione delle autoassociazioni
Alexandria prevede la possibilità di marcare come correlate due opere in modo tale da far apparire sulla pagina di una un collegamento all'altra.
Si è deciso di sviluppare questa funzionalità utilizzando delle **autoassociazioni**: ogni `Libro`, `Film` o `Videogioco` sarà correlato ad altre entità del suo stesso tipo tramite la relazione `è correlato a`.
![](img/3-3-autoassociazioni/autoassociazione.png)
> Inizialmente, si è considerato di aggiungere una unica autoassociazione alla entità `Elemento`, ma si è poi giunti alla conclusione che questo approccio sarebbe stato sbagliato: si sarebbero dovuti associare tutti i singoli `Elementi` creati da ciascun `Utente`, creando una quantità di correlazioni a crescita esponenziale!
> Una possibile estensione alla funzionalità si potrebbe ottenere aggiungendo un attributo _Tipo_ alla relazione `è correlato a`: esso permetterebbe agli `Utenti` di descrivere come due opere sono correlate tra loro ("sequel", "prequel", "stesso universo", etc...).

188
3-4-schema-finale.md Normal file
View file

@ -0,0 +1,188 @@
# Schema scheletro finale
Dopo aver costruito [lo schema scheletro](3-1-schema-scheletro.md), identificato [le gerarchie](3-2-gerarchie.md) e [le autoassociazioni](3-3-autoassociazioni.md), si è passati a ultimare lo schema relazionale, aggiungendoci **attributi**, **identificatori** e **cardinalità delle relazioni**.
Per farlo, ci si è basati sui contenuti della [descrizione](1-descrizione.md) e del [glossario](2-glossario.md): per comodità, si riportano qui le frasi della descrizione relative alle entità di cui si parla.
È allegato alla relazione il file [`3-4-schema-finale.drawio`](3-4-schema-finale.drawio): esso contiene lo schema scheletro finale di cui si vedono le immagini in questo capitolo.
## Legenda
![](img/3-4-relazioni/legenda.png)
## `Utenti`
> Chiunque può registrarsi al sito web scegliendo un username univoco e inserendo una password segreta (sarà [hashata](https://it.wikipedia.org/wiki/Funzione_di_hash) con l'algoritmo [bcrypt](https://it.wikipedia.org/wiki/Bcrypt) prima che venga inserita nel database), creando così un utente.
>
> Esisterà una tipologia particolare di utente: l'utente **amministratore**.
>
> Inoltre, potranno decidere di __bannare__ utenti dal sito, impedendo loro di effettuare l'accesso e di conseguenza di interagire con la loro raccolta.
![](img/3-4-relazioni/utente.png)
Per gli `Utenti`, si sono aggiunti gli attributi all'entità seguendo strettamente le specifiche, assieme a un attributo opzionale "email" per permettere un eventuale recupero dell'account nel caso che ci si sia dimenticati la password.
## `Elementi`
> Gli utenti potranno aggiungere _elementi_ alla loro raccolta multimediale.
>
> Un elemento rappresenta una copia di un libro, di un film o di un videogioco posseduta da un utente.
>
> Ogni elemento avrà associato uno **stato** da una lista di opzioni diversa per ogni tipologia: [...]
>
> Inoltre, ogni elemento avrà associata una **provenienza** da un'altra lista: [...]
> Un utente potrà lasciare una recensione ad ogni elemento presente nella sua raccolta.
>
> La recensione sarà composta da una valutazione (tra 0 e 100, dove 100 è la valutazione migliore), un commento e la data di pubblicazione.
![](img/3-4-relazioni/elemento.png)
### Sottoentità
![](img/3-2-gerarchie/gerarchia-1.png)
Gli `Elementi` sono stati suddivisi in tre sottoentità `Elemento (libro)`, `Elemento (film)` ed `Elemento (gioco)` per permettere loro di possedere attributi e relazioni di tipo diverso gli uni dagli altri; infatti, ognuna delle tre sottoentità è dotata di una associazione `istanza di` che le collega rispettivamente alle entità `Edizione (libro)`, `Film` e `Edizione (gioco)`.
Attributi e relazioni di queste sottoentità saranno descritti nelle sezioni successive.
### `Recensioni`
![](img/3-4-relazioni/recensioni.png)
Le `Recensioni` sono collegate agli `Elementi` attraverso la relazione `riguardante`.
Sono un caso di **identificatore esterno**: le `Recensioni` infatti usano come identificatore l'_id_ dell'`Elemento` a cui si riferiscono.
Si può inoltre dire che le `Recensioni` siano una **entità debole** rispetto agli `Elementi`, in quanto senza il suo relativo `Elemento`, una `Recensione` perderebbe importanti informazioni di contesto, e non avrebbe quindi più senso di esistere (infatti, senza `Elemento`, essa non sarebbe più dotata di un identificatore).
## `Libri`
> Ogni libro avrà una sua pagina in cui sarà presente il titolo originale, gli autori, i generi, un breve riassunto della trama, l'elenco di tutte le sue edizioni (sia in formato libro sia in formato audiolibro) e [...].
>
> Ciascuna edizione del libro avrà una seconda pagina con ulteriori informazioni, quali il suo titolo, la copertina, la casa editrice e il numero di pagine; ciascuna edizione sarà identificata da il relativo [codice ISBN](https://it.wikipedia.org/wiki/ISBN).
>
> Le edizioni in formato audiolibro avranno attributi diversi: invece che avere il numero di pagine e la copertina, essi avranno la durata in minuti e secondi della registrazione e opzionalmente un'immagine che rappresenti l'audiolibro.
![](img/3-4-relazioni/libri.png)
Lo schema dei `Libri` è stato realizzato seguendo in buona parte le specifiche; si sono però effettuate alcune aggiunte:
- Le `Edizioni` di un `Libro` sono state dotate di un _titolo_, che rappresenta il titolo dell'`Edizione` specifica (titolo in una lingua diversa, edizione speciale che cambia il titolo, etc...);
- Le `Edizioni` di un `Audiolibro` possono avere associato uno o più `Narratori`.
### Una ricorrenza nelle relazioni: il pattern "1NN0"
![](img/3-4-relazioni/inno-1.png)
![](img/3-4-relazioni/inno-2.png)
Osservando lo schema, si nota che le relazioni "narrata da" e "scritto da" sono molto simili tra loro: tutte e due sono **0 a N** nel lato che si collega all'opera (il `Libro` o una sua `Edizione`), sono **1 a N** dall'altro lato e si ricollegano a una entità con due soli attributi, _Nome_ e _ID_.
Questa particolare struttura compare in molte parti dello schema relazionale: per evitare di ridescriverla ogni volta e per permettere invece di referenziarla, si è deciso di darle il nome **1NN0** (leggi: "inno").
La lato dell'opera si ha una cardinalità **0 a N**, in modo da evitare agli utenti la compilazione obbligatoria di tutti i campi di un opera al momento della sua aggiunta, ma permettendo una loro compilazione più dettagliata in futuro, prevedendo anche casi in cui ad esempio un libro sia stato scritto da più autori.
Dato che si è voluto rendere possibili query come "quali `Libri` ha scritto questo autore" o "quali `Libri` ha narrato questo narratore" e che inserire nel database autori o narratori a cui non appartiene nessun libro non avrebbe alcun senso, si è scelto invece di usare una cardinalità **1 a N** dall'altro lato della relazione.
Infine, per l'entità connessa al lato _1 a N_ della relazione, si è deciso di usare un **identificatore surrogato**, in modo da permettere la modifica del _Nome_ associato senza dover andare a modificare tutte le opere.
### `Generi`
![](img/3-4-relazioni/generi-libri.png)
Notiamo che la relazione che associa un `Libro` a un `Genere` è molto simile alla struttura _1NN0_, ma essa ha una cardinalità **0 a N** anche dal lato dell'entità `Genere`.
Questo perchè si intende aggiungere alcuni `Generi` al database tra cui gli utenti potranno scegliere prima ancora che esistano dei libri.
### `Editori`
![](img/3-4-relazioni/editore.png)
Tutti i codici ISBN contengono al loro interno [un codice univoco che identifica l'editore](https://it.wikipedia.org/wiki/ISBN#Editore) di un libro; si è quindi deciso di usare questo codice per identificare l'entità `Editore`.
### Correlazioni
> [...] e opzionalmente una lista di opere correlate (sequel, prequel, libri ambientati nello stesso universo, etc)
![](img/3-4-relazioni/autoassoc-libri.png)
Come menzionato [in precedenza](3-3-autoassociazioni.md), l'entità `Libro` è dotata di una autoassociazione che permette di identificare gli altri `Libri` ad essa correlati.
## `Film`
> Ogni film avrà una sua pagina in cui sarà presente il titolo originale, i titoli nelle varie lingue (identificati dal [codice ISO 639 della lingua](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)), una sinossi della trama, la durata, la casa produttrice, il cast, e, come per i libri, una lista opzionale di pellicole correlate.
>
> I film saranno identificati dal loro [codice EIDR](https://ui.eidr.org/search), e per ciascuno di essi verrà calcolata la valutazione media dalle recensioni, che sarà visualizzata sulla pagina assieme a un campione di recensioni.
![](img/3-4-relazioni/film.png)
### Il pattern _1NN0_ nei `Film`
![](img/3-4-relazioni/inno-3.png)
Nello schema dei `Film`, si può notare il pattern _1NN0_, in corrispondenza alla relazione `prodotto da`.
### `vi ha preso parte`: una relazione _1NN0_ ternaria
![](img/3-4-relazioni/ternaria.png)
Nello schema dei film è presente la **relazione ternaria** `vi ha preso parte`.
Essa associa una persona (`Cast`) a un `Film`, specificando il `Ruolo` ("attore", "regista", "sceneggiatore"...) per cui vi ha preso parte.
È stata modellata in questo modo per consentire query avanzate sul cast di un `Film`: ad esempio, "in quali film Quentin Tarantino ha avuto il ruolo di regista", oppure "che ruoli ha ricoperto Johnny Depp nei film usciti dopo il 2010".
### `Generi`
![](img/3-4-relazioni/generi-film.png)
Come per i `Libri`, l'entità `Genere` è coinvolta in una _1NN0_ con cardinalità **0 a N** dal lato del `Genere`.
### Correlazioni
![](img/3-4-relazioni/autoassoc-film.png)
Come i `Libri`, anche i `Film` hanno un'autoassociazione per determinare le pellicole correlate.
### Localizzazione
![](img/3-4-relazioni/entita-debole.png)
Simile al pattern _1NN0_, ma fondamentalmente diversa è la relazione `in altre lingue`: essa ha cardinalità _0 a N_ dal lato dei `Film`, e _1 a 1_ dal lato dell'entità `Localizzazione`; in più, l'associazione è identificatore esterno di `Localizzazione`.
L'entità `Localizzazione` rappresenta il **titolo** di un `Film` tradotto in una lingua: ad esempio, _Il Padrino_ è una localizzazione in "`it`" (italiano) del `Film` _The Godfather_.
Il suo identificatore è composto dal codice ISO della lingua a cui si riferisce e dall'identificatore del `Film` a cui essa si riferisce: è dunque una **entità debole**.
> Nei `Libri` e nei `Giochi` non è stato necessario creare questa entità perchè nei `Libri` lingue diverse hanno codici ISBN diversi (e quindi è possibile inserire i titoli localizzati all'interno dell'entità `Edizione`), e per i `Giochi` è molto raro avere titoli tradotti.
## `Giochi`
> Ogni videogioco avrà una sua pagina in cui sarà presente il titolo, lo sviluppatore, il publisher, una breve descrizione del gioco, l'elenco di tutte le piattaforme in cui esso è disponibile e, come per libri e film, un elenco di altri giochi correlati.
>
> Per ogni piattaforma sarà disponibile una sottopagina, che conterrà la [box art](https://vgboxart.com/) di quella versione, il nome dello studio che ha effettuato il [porting](https://en.wikipedia.org/wiki/Porting#Porting_of_video_games) ed eventualmente il titolo [se diverso da quello principale](https://it.wikipedia.org/wiki/Payday_2#Crimewave_Edition).
![](img/3-4-relazioni/giochi.png)
### `Edizioni`
![](img/3-4-relazioni/giochi-e-edizioni.png)
Quelle che [nella descrizione](/1-descrizione.md) vengono chiamate _sottopagine_ sono state realizzate nello schema attraverso l'entità `Edizione`: una `Edizione` rappresenta una versione di un gioco pubblicata su una specifica piattaforma (PC, PS4, Xbox One, etc...).
Come per gli `Elementi (libro)`, gli `Elementi (gioco)` saranno istanziati relativamente a una specifica `Edizione` di un gioco.
### Il pattern _1NN0_ nei `Giochi`
![](img/3-4-relazioni/inno-4.png)
Il pattern _1NN0_ è presente anche all'interno dello schema dei `Giochi`: si può notare nelle relazioni `sviluppato da`, `pubblicato da` e `portato da`.
### `Generi`
![](img/3-4-relazioni/generi-giochi.png)
Come i `Libri` e i `Film`, anche i `Giochi` hanno una relazione `appartiene a` che li collega a uno o più `Generi`.
### `Giochi` correlati
![](img/3-4-relazioni/autoassoc-giochi.png)
Ancora, anche i `Giochi` hanno un'autoassociazione per determinare le correlazioni tra di essi.

View file

@ -0,0 +1,37 @@
# Eliminazione delle gerarchie
Per effettuare la progettazione logica è necessaria come prima cosa **eliminare le gerarchie IsA** createsi [durante la fase di progettazione concettuale](3-2-gerarchie.md).
Si ricorda che in Alexandria sono presenti due gerarchie: una relativa agli `Elementi` e una relativa alle `Edizioni` dei `Libri`.
## Gerarchia delle `Edizioni`
![](img/4-1-eliminazione-gerarchie/gerarchia-edizioni.png)
La gerarchia delle `Edizioni` è una gerarchia **totale** ed **esclusiva**; gli approcci possibili sono dunque 4:
- **Mantenimento delle entità**: Un'opzione sempre possibile, ma che porta a un numero di accessi maggiore e quindi a una velocità di interrogazione minore rispetto alle due alternative.
- **Collasso verso l'alto**: Essendo una relazione esclusiva, collassarla verso l'alto porterebbe ad _almeno_ un 50% di valori nulli nella tabella `Edizione` risultante, portando a un significativo spreco di memoria.
- **Collasso verso l'alto con unione**: Sarebbe possibile effettuare il _collasso verso l'alto_ unendo però le coppie di attributi `{"Copertina", "Immagine"}` e `{"Pagine", "Durata"}` (facendo riferimento rispettivamente alle pagine del libro e ai secondi dell'audiolibro) per rendere 0 i valori nulli introdotti nella tabella, a costo di parte dell'integrità della base di dati.
- **Collasso verso il basso**: Porterebbe alla duplicazione dell'entità `Edizione` e delle associazioni 1 a N con cardinalità N dal lato di `Edizione`; si creerebbe un nuovo tipo di `Elemento`, "`Elemento (audiolibro)`".
Si è deciso di **collassare la gerarchia verso il basso** perchè si è reputato importante mantenere integra, veloce e compatta la base di dati, anche a costo di maggiore complessità progettuale.
## Gerarchia degli `Elementi`
![](img/4-1-eliminazione-gerarchie/gerarchia-elementi.png)
La gerarchia degli `Elementi` è **non totale** ed **esclusiva**. Possiamo dunque applicare i seguenti approcci:
- **Mantenimento delle entità**: Un'opzione sempre possibile, ma che porta a un numero di accessi maggiore e quindi a una velocità di interrogazione minore rispetto alle due alternative.
- **Collasso verso l'alto**: Collassare direttamente verso l'alto sarebbe l'opzione peggiore, in quanto aggiungerebbe 12 nuovi attributi con _almeno_ il 75% dei valori nulli (più un selettore), sprecando più memoria del necessario.
- **Collasso verso l'alto con unione**: Per minimizzare i valori nulli, si potrebbero unire gli attributi `{"Provenienza", "Stato"}` in uno unico, verificando che vengano inseriti valori validi attraverso vincoli di integrità; in questo caso, si introdurrebbero solo 4 nuovi attributi ("istanza di"), con però comunque _almeno_ il 75% di valori nulli, costando memoria (ma meno di quanta se ne sarebbe spesa in un normale collasso).
- **Collasso verso il basso**: Porterebbe alla creazione di quattro tabelle `Elemento` e a quattro tabelle `Recensione` relative a ogni tipo di `Elemento`, aumentando la complessità progettuale.
Anche qui si è deciso di **collassare la gerarchia verso il basso**, in quanto il collasso verso il basso favorisce le entità molto specializzate come gli `Elementi`; inoltre, adottare il collasso verso il basso permette di espandere con facilità il database in futuro per aggiungerci altri tipi di `Elementi`, in quanto basterà poi creare due nuove tabelle `Elemento` e `Recesione` per ogni tipo che si vorrà aggiungere.

View file

@ -0,0 +1,19 @@
# Eliminazione delle chiavi esterne
In Alexandria sono presenti solo due **chiavi esterne**: una nelle entità `Recensione` e l'altra nell'entità `Localizzazione`.
## Eliminazione della chiave di `Recensione`
![](img/4-2-eliminazione-chiavi-esterne/chiave-recensioni.png)
In questo caso, si è aggiunto a `Recensione` l'attributo "ID elemento", che corrisponderà all'ID dell'`Elemento` a cui si riferisce:
![](img/4-2-eliminazione-chiavi-esterne/after-recensioni.png)
## Eliminazione della chiave di `Localizzazione`
![](img/4-2-eliminazione-chiavi-esterne/chiave-localizzazione.png)
Anche in questo caso si è trasformata la chiave esterna in un attributo "EIDR film" che corrisponderà all'EIDR del film il cui titolo è stato tradotto.
![](img/4-2-eliminazione-chiavi-esterne/after-localizzazione.png)

View file

@ -0,0 +1,4 @@
# Trasformazione degli attributi composti
Lo schema relazionale di Alexandria non prevede alcun **attributo composto**, pertanto non c'è nulla da trasformare.

68
4-4-dati-derivati.md Normal file
View file

@ -0,0 +1,68 @@
# Dati derivati
In Alexandria non sono presenti molti dati quantitativi: la maggior parte degli attributi sono infatti qualitativi, e come tali meglio descritti da stringhe.
Si è considerata la possibilità di inserire nella base di dati un attributo contenente il **conteggio** di `Elementi` posseduti da un utente.
![](img/4-4-dati-derivati/conteggio-elementi.png)
Si riportano sotto tutti i calcoli effettuati per decidere se aggiungere o no il dato derivato.
## Tabella dei volumi
Secondo una stima effettuata, l'utente medio di Alexandria leggerà all'anno 18 libri, ascolterà 6 audiolibri, guarderà 52 film e giocherà a 24 giochi, per un totale di circa 100 `Elementi` per `Utente` all'anno.
Si ottiene, dunque, la seguente tabella dei volumi:
| Concetto | Tipo | Volume |
|----------|------|--------|
| `Utente` | Entità | **1**/utente |
| `Elemento (audiolibri)` | Entità | **6**/utente/anno |
| `Elemento (libro)` | Entità | **18**/utente/anno |
| `Elemento (film)` | Entità | **52**/utente/anno |
| `Elemento (gioco)` | Entità | **24**/utente/anno |
Si considera solo la categoria degli audiolibri: se per essi è conveniente mantenere il dato derivato, allora lo sarà anche per tutti gli altri tipi di elemento, in quanto hanno volumi maggiori.
## Tabella delle operazioni
Si stima che ogni utente riceverà circa 500 visite alla suo profilo all'anno.
Si sono valutate due diverse operazioni:
| Operazione | Descrizione | Tipo | Frequenza | Schema |
|------------|-------------|------|-----------|--------|
| __OP1__ | Creazione di un nuovo `Elemento (audiolibro)` | Interattiva | **6**/utente/anno | `Elemento (audiolibro)` |
| __OP2__ | Visualizzazione del conteggio di `Elementi` di qualsiasi tipo creati da un `Utente` specifico | Interattiva | **500**/utente/anno | `Elemento (audiolibro)` |
## Tabella dei costi
Si sono utilizzati i seguenti costi per realizzare la tabella dei costi:
- **read**: costo **1**
- **write**: costo **2**
- **update**: composta da 1 read e 1 write, costo **3**
### Senza dato derivato
| Operazione | Procedura | Costi | Costo totale |
|------------|-----------|-------|--------------|
| __OP1__ | Si inserisce una nuova tupla nella tabella `Elemento (audiolibro)`. | 1 write | **2** |
| __OP2__ | Si interroga la tabella `Elemento (audiolibro)`, filtrando le tuple che non sono state create dall'utente desiderato, e si contano le tuple restituite. | 6 read | **6** |
### Con dato derivato
| Operazione | Procedura | Costi | Costo totale |
|------------|-----------|-------|--------------|
| __OP1__ | Si inserisce una nuova tupla nella tabella `Elemento (audiolibro)` e si aggiorna il dato derivato della tupla dell'`Utente` creatore. | 1 write + 1 update | **5** |
| __OP2__ | Si va a vedere il dato derivato nella tabella dell'`Utente` desiderato. | 1 read | **1** |
## Risultato
| Metodo | Costo __OP1__ | Costo __OP2__ | Costo totale |
|--------|---------------|---------------|--------------|
| Senza dato derivato | 2 * 100 | 6 * 500 | 3200 |
| Con dato derivato | 5 * 100 | 1 * 500 | 1000 |
Dato che 1000 < 3200, conviene **creare il dato derivato** nella tabella `Utente`.
La stessa cosa vale per gli `Elementi` di libri, film e giochi: avendo volumi maggiori, essi possono solo aumentare il costo dell'__OP2__ _senza dato derivato_.

224
4-5-schema-logico.md Normal file
View file

@ -0,0 +1,224 @@
# Creazione dello schema logico
Di seguito si riporta l'intero schema logico dopo aver effettuato tutte le trasformazioni previste dalla fase di progettazione logica.
## Legenda
- Entità
- **Chiave primaria**
- → [Chiave esterna](#legenda)
- _Opzionale_
- [](4-4-dati-derivati.md) Dato derivato
## Categoria generale
### Utente
- **Username**
- Password
- _Email_
- È amministratore
- È bannato
- [](4-4-dati-derivati.md) Elementi (libro) posseduti
- [](4-4-dati-derivati.md) Elementi (audiolibro) posseduti
- [](4-4-dati-derivati.md) Elementi (film) posseduti
- [](4-4-dati-derivati.md) Elementi (gioco) posseduti
## Categoria condivisa tra libri e audiolibri
### Libro
- **ID**
- Titolo primario
- _Sinossi_
### Appartenenza a genere (libro)
- **ID Genere** → [Genere (libro)](#genere-libro)
- **ID Libro** → [Libro](#libro)
### Autore
- **ID**
- Nome
### Correlazioni (libro)
- **ID1** → [Libro](#libro)
- **ID2** → [Libro](#libro)
### Editore
- **Parte ISBN**
- Nome
### Genere (libro)
- **ID**
- Nome
### Scritto da
- **ID Autore** → [Autore](#autore)
- **ID Libro** → [Libro](#libro)
## Categoria libri
### Edizione (libro)
- **ISBN**
- Titolo
- _Pagine_
- _Copertina_
- Relativa a → [Libro](#libro)
### Elemento (libro)
- **ID**
- Istanza di → [Edizione (libro)](#edizione-libro)
- Appartiene a → [Utente](#utente)
- _Stato_
- _Provenienza_
### Recensione (libro)
- **ID** → [Elemento (libro)](#elemento-libro)
- Commento
- Valutazione
- Data
## Schema degli audiolibri
### Edizione (audiolibro)
- **ISBN**
- Titolo
- _Durata_
- _Immagine_
- Relativa a → [Libro](#libro)
### Elemento (audiolibro)
- **ID**
- Istanza di → [Edizione (audiolibro)](#edizione-audiolibro)
- Appartiene a → [Utente](#utente)
- _Stato_
- _Provenienza_
### Narrata da
- **ID Edizione** → [Edizione (audiolibro)](#edizione-audiolibro)
- **ID Narratore** → [Narratore](#narratore)
### Narratore
- **ID**
- Nome
### Recensione (audiolibro)
- **ID** → [Elemento (audiolibro)](#elemento-audiolibro)
- Commento
- Valutazione
- Data
## Categoria film
### Film
- **EIDR**
- Titolo
- _Sinossi_
- _Durata_
- _Locanddina_
### Appartenenza a genere (film)
- **ID Genere** → [Genere](#genere-film)
- **EIDR** → [Film](#film)
### Cast
- **ID**
- Nome
### Correlazioni (film)
- **EIDR1** → [Film](#film)
- **EIDR2** → [Film](#film)
### Elemento (film)
- **ID**
- _Stato_
- _Provenienza_
- Istanza di → [Film](#film)
- Appartiene a → [Utente](#utente)
### Genere (film)
- **ID**
- Nome
### Localizzazione
- **Lingua**
- **EIDR** → [Film](#film)
- Titolo localizzato
### Prodotto da
- **ID Studio** → [Studio](#studio-film)
- **EIDR** → [Film](#film)
### Recensione (film)
- **ID** → [Recensione (film)](#elemento-film)
- Commento
- Valutazione
- Data
### Ruolo
- **ID**
- Nome
### Studio (film)
- **ID**
- Nome
### Vi ha preso parte
- **EIDR** → [Film](#film)
- **ID Cast** → [Cast](#cast)
- **ID Ruolo** → [Ruolo](#ruolo)
## Categoria giochi
### Gioco
- **ID**
- Nome
- _Descrizione_
### Appartenenza a genere (gioco)
- **ID Gioco** → [Gioco](#gioco)
- **ID Genere** → [Genere (gioco)](#genere-gioco)
### Correlazioni (gioco)
- **ID1** → [Gioco](#gioco)
- **ID2** → [Gioco](#gioco)
### Edizione (gioco)
- **ID**
- _Titolo alternativo_
- Piattaforma
- _Box art_
- Relativa a → [Gioco](#gioco)
### Elemento (gioco)
- **ID**
- _Stato_
- _Provenienza_
- Istanza di → [Edizione (gioco)](#edizione-gioco)
- Appartiene a → [Utente](#utente)
### Genere (gioco)
- **ID**
- Nome
### Portato da
- **ID Edizione** → [Edizione (gioco)](#edizione-gioco)
- **ID Studio** → [Studio (gioco)](#studio-gioco)
### Prodotto da
- **ID Gioco** → [Gioco](#gioco)
- **ID Studio** → [Studio (gioco)](#studio-gioco)
### Recensione (gioco)
- **ID** → [Recensione (gioco)](#elemento-gioco)
- Commento
- Valutazione
- Data
### Studio (gioco)
- **ID**
- Nome
### Sviluppato da
- **ID Gioco** → [Gioco](#gioco)
- **ID Studio** → [Studio (gioco)](#studio-gioco)

3
4-6-normalizzazione.md Normal file
View file

@ -0,0 +1,3 @@
# Verifica di normalizzazione
Dopo aver costruito lo [schema logico](4-5-schema-logico.md), si è constatato che la base di dati fosse in forma normale, e che non fosse necessaria alcuna ulteriore modifica.

View file

@ -0,0 +1,55 @@
# Tecnologia database
## Database Management System
Si è scelto di utilizzare **PostgreSQL** (_Postgres_) come DBMS in quanto è quello con il quale i membri del gruppo erano più famigliari.
## Strumenti aggiuntivi
Per assistere nella progettazione fisica, sono stati usati due strumenti per la manipolazione di database Postgres:
- [pgAdmin 4](https://www.pgadmin.org/)
- Il plugin [Database Tools and SQL](https://plugins.jetbrains.com/plugin/10925-database-tools-and-sql) per IDE basati su IntelliJ
## Hosting
Per facilitare la collaborazione, si è scelto di condividere un'**istanza remota** di PostgreSQL installata su un server Ubuntu 18.04.4 LTS, alla quale ci si è connessi con username e password individuali.
________________________________________________
```bash
lsb_release -a
```
```text
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
```
________________________________________________
```sql
SELECT version();
```
| version |
|---------|
| PostgreSQL 10.12 (Ubuntu 10.12-0ubuntu0.18.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit |
## Riproduzione del database
È allegato alla relazione il file [`5-database.sql`](5-database.sql), contenente tutte le istruzioni necessarie per ricreare il database descritto in questo capitolo.
Esso è stato ottenuto tramite [`pg_dump`](https://www.postgresql.org/docs/9.3/app-pgdump.html), un'utilità per l'archiviazione di database Postgres, eseguito con il seguente comando Bash:
```bash
pg_dump --dbname=alexandria --schema='public' --file="5-database.sql" --no-owner --no-acl
```
È possibile ricreare il database eseguendo manualmente tutte le istruzioni contenute nel file `.sql`, oppure eseguendo [`pg_restore`](https://www.postgresql.org/docs/9.3/app-pgrestore.html), la controparte di `pg_dump` per il ripristino, con il seguente comando Bash:
```bash
pg_restore --dbname="alexandria" --schema="public" --file="5-database.sql"
```

13
5-2-creazione-database.md Normal file
View file

@ -0,0 +1,13 @@
# Creazione database
Come primo passo della progettazione fisica si è creato un nuovo database su PostgreSQL attraverso il seguente comando [Bash](https://it.wikipedia.org/wiki/Bash):
```bash
createdb alexandria
```
Esso è equivalente alla seguente istruzione SQL:
```sql
CREATE DATABASE alexandria;
```

291
5-3-creazione-tabelle.md Normal file
View file

@ -0,0 +1,291 @@
# Creazione tabelle
Dopo aver creato il database, il secondo passo della progettazione fisica è stato quello di convertire lo schema logico in un database Postgres.
In generale:
- Le **entità** sono diventate _TABLES_ (tabelle);
- Gli **attributi opzionali** sono diventati _COLUMNS_ (colonne);
- Gli **attributi obbligatori** sono diventati _COLUMNS_ con il vincolo _NOT NULL_;
- Le **chiavi primarie** sono state implementate come _PRIMARY KEYS_ (chiavi primarie);
- Le **chiavi esterne** sono state implementate come _FOREIGN KEYS_ (chiavi esterne);
- Le **chiavi surrogate** sono state implementate come _PRIMARY KEYS_ autoincrementate tramite _SEQUENCES_ (sequenze);
- I **dati derivati** sono stati implementati come _COLUMNS_ aventi dei _TRIGGER_ che le aggiornino.
## Schema dei nomi delle tabelle
Tutte le tabelle sono state istanziate con il nome che le corrispondenti entità avevano nello schema logico, sostituendo tutte le lettere maiuscole con **lettere minuscole** `a-z`, spazi con **underscore** `_` e rimuovendo le parentesi con il loro contenuto.
Inoltre, a tutte le tabelle tranne `utente` è stato dato un nome prefissato da `libro_`, `audiolibro_`, `film_` e `gioco_` per indicare la categoria a cui le entità appartenevano nello schema logico.
### Esempi
| Entità | Tabella |
|--------|---------|
| [`Utente`](4-5-schema-logico.md#utente) | `utente` |
| [`Libro`](4-5-schema-logico.md#libro) | `libro` |
| [`Edizione (libro)`](4-5-schema-logico.md#edizione-libro) | `libro_edizione` |
| [`Cast`](4-5-schema-logico.md#cast) | `film_cast` |
## Creazione tabelle
Si riportano solo le tabelle con qualche particolarità; le tabelle per la quale la conversione è banale sono omesse da questo file (ma non dal file [`5-database.sql`](5-database.sql)).
### `audiolibro_edizione`
```sql
CREATE TABLE public.audiolibro_edizione (
isbn character(13) NOT NULL,
titolo character varying NOT NULL,
durata interval,
immagine bytea,
relativa_a integer NOT NULL,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) >= (0)::double precision))
);
ALTER TABLE ONLY public.audiolibro_edizione
ADD CONSTRAINT audiolibro_edizione_pkey PRIMARY KEY (isbn);
```
La durata delle edizioni degli audiolibri è di tipo _interval_, che rappresenta un intervallo di tempo con la precisione di centesimi di secondo; l'immagine dell'audiolibro ha invece tipo _bytea_, e sarà salvata nel database come un blob binario di dati.
Inoltre, la durata è dotata di un _CHECK_ che impedisce che essa sia minore di 0, convertendo l'_interval_ in secondi e controllando che essi siano maggiori di 0.
### `audiolibro_recensione`
```sql
CREATE TABLE public.audiolibro_recensione (
id bigint NOT NULL,
commento text NOT NULL,
valutazione smallint NOT NULL,
data timestamp without time zone DEFAULT now() NOT NULL,
CONSTRAINT audiolibro_recensione_valutazione_check CHECK (((valutazione >= 0) AND (valutazione <= 100)))
);
ALTER TABLE ONLY public.audiolibro_recensione
ADD CONSTRAINT audiolibro_recensione_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.audiolibro_recensione
ADD CONSTRAINT id FOREIGN KEY (id) REFERENCES public.audiolibro_elemento(id);
```
Per minimizzare valori nulli, si è tradotta l'associazione binaria 1 a 1 `relativa a` in due tabelle separate, usando in una delle due una chiave esterna come chiave primaria.
Si notino dunque i due _CONSTRAINT_ `audiolibro_recensione_pkey` e `id`.
La valutazione delle recensioni deve essere obbligatoriamente tra 0 e 100: a tale scopo, è stato introdotto un _CHECK_ sulla tabella che verifichi questa condizione.
La data di pubblicazione è rappresentata da un _timestamp_, tipo che rappresenta un istante specifico di tempo con precisione fino ai microsecondi.
### `film`
```sql
CREATE TABLE public.film (
eidr character(34) NOT NULL,
titolo character varying NOT NULL,
sinossi text,
locandina bytea,
durata interval,
CONSTRAINT durata_check CHECK ((date_part('epoch'::text, durata) > (0)::double precision))
);
ALTER TABLE ONLY public.film
ADD CONSTRAINT film_pkey PRIMARY KEY (eidr);
```
Nella tabella `film` compare nuovamente il _CHECK_ utilizzato nelle `audiolibro_edizioni` per la durata, e lo stesso tipo _bytea_ per la locandina.
Si può notare nella tabella compare il tipo _char(34)_: essendo gli EIDR sempre lunghi 34 caratteri, si è scelto si minimizzare lo spazio di archiviazione utilizzato rendendo il campo a lunghezza non variabile.
### `film_correlazioni`
```sql
CREATE TABLE public.film_correlazioni (
eidr_1 character(34) NOT NULL,
eidr_2 character(34) NOT NULL
);
ALTER TABLE ONLY public.film_correlazioni
ADD CONSTRAINT film_correlazioni_pkey PRIMARY KEY (eidr_1, eidr_2);
ALTER TABLE ONLY public.film_correlazioni
ADD CONSTRAINT eidr_1 FOREIGN KEY (eidr_1) REFERENCES public.film(eidr);
ALTER TABLE ONLY public.film_correlazioni
ADD CONSTRAINT eidr_2 FOREIGN KEY (eidr_2) REFERENCES public.film(eidr);
```
L'autoassociazione delle correlazioni è stata implementata attraverso una **tabella ponte** che collega due film attraverso i loro `eidr`.
`eidr_1` ed `eidr_2` sono due chiavi esterne separate, e insieme formano la **chiave primaria composta** della tabella.
### `film_vi_ha_preso_parte`
```sql
CREATE TABLE public.film_vi_ha_preso_parte (
eidr character(34) NOT NULL,
id_cast integer NOT NULL,
id_ruolo integer NOT NULL
);
ALTER TABLE ONLY public.film_vi_ha_preso_parte
ADD CONSTRAINT film_vi_ha_preso_parte_pkey PRIMARY KEY (eidr, id_cast, id_ruolo);
ALTER TABLE ONLY public.film_vi_ha_preso_parte
ADD CONSTRAINT eidr FOREIGN KEY (eidr) REFERENCES public.film(eidr);
ALTER TABLE ONLY public.film_vi_ha_preso_parte
ADD CONSTRAINT id_cast FOREIGN KEY (id_cast) REFERENCES public.film_cast(id);
ALTER TABLE ONLY public.film_vi_ha_preso_parte
ADD CONSTRAINT id_ruolo FOREIGN KEY (id_ruolo) REFERENCES public.film_ruolo(id);
```
L'associazione ternaria è stata realizzata con un'altra **tabella ponte**, avente una **chiave primaria composta** e tre chiavi esterne separate.
### `elemento_id_seq`
```sql
CREATE SEQUENCE public.elemento_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
```
Si è deciso di rendere **univoci** gli `id` di **tutti gli elementi**, qualsiasi fosse il loro tipo.
Per realizzare ciò si è creata una _SEQUENCE_ unica che viene poi usata da tutte le tabelle `*_elemento` per generare i nuovi id.
### Stato e provenienza
```sql
CREATE TYPE public.gioco_provenienza AS ENUM (
'GRATUITO',
'ACQUISTATO',
'IN_ABBONAMENTO',
'PRESO_IN_PRESTITO',
'NON_PIU_POSSEDUTO',
'ALTRO'
);
CREATE TYPE public.gioco_stato AS ENUM (
'DA_INIZIARE',
'INIZIATO',
'FINITO',
'COMPLETATO',
'NON_APPLICABILE'
);
```
Gli stati e le provenienze dei vari elementi sono state realizzate creando _ENUM_ contenenti tutte le possibili opzioni selezionabili dall'utente, e utilizzandoli come tipo delle relative colonne; in questo modo, si impedisce l'immissione di valori non validi nelle colonne.
### `gioco_elemento`
```sql
CREATE TABLE public.gioco_elemento (
id bigint DEFAULT nextval('public.elemento_id_seq'::regclass) NOT NULL,
stato public.gioco_stato,
provenienza public.gioco_provenienza,
istanza_di integer NOT NULL,
appartiene_a character varying NOT NULL
);
ALTER TABLE ONLY public.gioco_elemento
ADD CONSTRAINT gioco_elemento_pkey PRIMARY KEY (id);
ALTER TABLE ONLY public.gioco_elemento
ADD CONSTRAINT appartiene_a FOREIGN KEY (appartiene_a) REFERENCES public.utente(username);
ALTER TABLE ONLY public.gioco_elemento
ADD CONSTRAINT istanza_di FOREIGN KEY (istanza_di) REFERENCES public.gioco_edizione(id);
CREATE FUNCTION public.update_n_giochi() RETURNS trigger
LANGUAGE plpgsql
AS $$BEGIN
IF (TG_OP = 'DELETE') THEN
UPDATE utente
SET gioco_elementi_posseduti = gioco_elementi_posseduti - 1
WHERE utente.username = old.appartiene_a;
RETURN old;
ELSIF (TG_OP = 'INSERT') THEN
UPDATE utente
SET gioco_elementi_posseduti = gioco_elementi_posseduti + 1
WHERE utente.username = new.appartiene_a;
RETURN new;
END IF;
END;
$$;
CREATE TRIGGER numero_giochi_trigger BEFORE INSERT OR DELETE
ON public.gioco_elemento
FOR EACH ROW EXECUTE PROCEDURE public.update_n_giochi();
```
Le colonne `stato` e `provenienza` utilizzano il relativo _ENUM_ creato in precedenza.
La colonna `id` ha un valore di _DEFAULT_ particolare: `nextval('public.elemento_id_seq'::regclass)`.
Ciò significa che, se non viene specificato un `id` durante un inserimento, alla riga verrà assegnato automaticamente il valore corrente della _SEQUENCE_ `public.elemento_id_seq` descritta in precedenza, aumentandone inoltre il valore di 1.
Nella tabella è presente anche un _TRIGGER_, che incrementa o decrementa il conteggio degli elementi dell'utente a cui essi appartengono quando uno o più elementi vengono inseriti o rimossi.
### `libro_edizione`
```sql
CREATE FUNCTION public.is_numeric(text character varying) RETURNS boolean
LANGUAGE plpgsql STRICT
AS $_$DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;$_$;
CREATE TABLE public.libro_edizione (
isbn character(13) NOT NULL,
titolo_edizione character varying NOT NULL,
pagine integer,
copertina bytea,
relativa_a integer NOT NULL,
CONSTRAINT libro_edizione_isbn_check CHECK ((public.is_numeric(("substring"((isbn)::text, 1, 12))::character varying) AND (public.is_numeric(("right"((isbn)::text, 1))::character varying) OR ("right"((isbn)::text, 1) ~~ '%X'::text)))),
CONSTRAINT libro_edizione_pagine_check CHECK ((pagine >= 0))
);
ALTER TABLE ONLY public.libro_edizione
ADD CONSTRAINT libro_edizione_pkey PRIMARY KEY (isbn);
ALTER TABLE ONLY public.libro_edizione
ADD CONSTRAINT relativa_a FOREIGN KEY (relativa_a) REFERENCES public.libro(id);
```
La tabella delle edizioni di un libro include due _CHECK_: uno che controlla che le pagine, se specificate, siano un numero positivo, e un'altro che controlla che gli ISBN siano in un formato valido.
In particolare, per quest'ultimo, è stata creata una funzione di utilità `is_numeric`, che verifica che tutti i caratteri di una stringa siano numerici: questa funzione viene poi usata per controllare che tutti i caratteri dell'ISBN siano numeri, permettendo però anche una `X` in ultima posizione (l'ultima cifra degli ISBN più vecchi era in base-11 e utilizzava la lettera X come 10).
### `utente`
```sql
CREATE TABLE public.utente (
username character varying NOT NULL,
password bytea NOT NULL,
email character varying,
is_admin boolean DEFAULT false NOT NULL,
is_banned boolean DEFAULT false NOT NULL,
libro_elementi_posseduti integer DEFAULT 0 NOT NULL,
audiolibro_elementi_posseduti integer DEFAULT 0 NOT NULL,
film_elementi_posseduti integer DEFAULT 0 NOT NULL,
gioco_elementi_posseduti integer DEFAULT 0 NOT NULL
);
ALTER TABLE ONLY public.utente
ADD CONSTRAINT username PRIMARY KEY (username);
```
La password, essendo un [hash](https://it.wikipedia.org/wiki/Funzione_di_hash), è rappresentata come un dato binario (_bytea_).
Le colonne `is_admin` e `is_banned` hanno un valore di default di _false_, in quanto alla creazione gli utenti non saranno amministratori o bannati.
Le colonne `*_elementi_posseduti` sono i dati derivati che rappresentano quanti elementi di ogni tipo possiede un dato utente: per i nuovi utenti, questo valore sarà 0.
Queste colonne saranno poi incrementate dai trigger presenti nelle quattro tabelle `*_elemento`.

2180
5-database.sql Normal file

File diff suppressed because it is too large Load diff

87
6-operazioni.md Normal file
View file

@ -0,0 +1,87 @@
# Query preprogrammate per l'utilizzo del database
Si sono inserite in questo capitolo della relazione alcuni esempi di query che permetteranno al sito web di interagire con la base di dati.
Come nel caso della [creazione tabelle](5-3-creazione-tabelle.md), si elencano solo le query più significative.
## Creazione di un nuovo utente
```sql
INSERT INTO utente (username, password, email) VALUES ($username, $hashed_password, $email);
```
## Promozione di un utente ad amministratore
```sql
UPDATE utente SET is_admin = true WHERE username = $username;
```
## Creazione di un elemento relativo a un libro non esistente nel database
```sql
INSERT INTO libro (titolo_primario) VALUES ($titolo);
INSERT INTO libro_edizione (isbn, titolo_edizione, relativa_a) VALUES ($isbn, $titolo, currval('libro_id_seq'));
INSERT INTO libro_elemento (istanza_di, appartiene_a) VALUES ($isbn, $username);
```
## Creazione di una recensione relativa a un elemento
```sql
INSERT INTO libro_recensione (id, commento, data, valutazione) VALUES ($isbn, $commento, now(), $valutazione);
```
## Conteggio degli elementi posseduti da un utente
```sql
SELECT
libro_elementi_posseduti libri,
audiolibro_elementi_posseduti audiolibri,
film_elementi_posseduti film,
gioco_elementi_posseduti giochi,
(libro_elementi_posseduti + audiolibro_elementi_posseduti + film_elementi_posseduti + gioco_elementi_posseduti) totale
FROM utente
WHERE username = $username;
```
## Conteggio del numero totale di edizioni di libri presenti nel database
```sql
SELECT COUNT(*) FROM libro_edizione;
```
## Conteggio del numero totale di edizioni di libri di ogni autore
```sql
SELECT COUNT(*)
FROM libro_edizione
WHERE relativa_a IN (
SELECT l.id
FROM libro l
JOIN libro_scritto_da lsd on l.id = lsd.id_libro
JOIN libro_autore la on lsd.id_autore = la.id
WHERE la.id = $id_autore
);
```
## Visualizzazione della valutazione media di un gioco
```sql
SELECT AVG(gr.valutazione)
FROM gioco_recensione gr
JOIN gioco_elemento gel on gr.id = gel.id
JOIN gioco_edizione ge on gel.istanza_di = ge.id
JOIN gioco g on ge.relativa_a = g.id
WHERE g.id = $id_gioco;
```
## Visualizzazione di tutte le edizioni di un dato editore
```sql
SELECT *
FROM libro_editore ld
JOIN libro_edizione lz
ON ld.parte_isbn = substr(lz.isbn, 6, length(ld.parte_isbn))
WHERE ld.nome = $nome_editore;
```

View file

@ -1,13 +0,0 @@
# Identificazione delle autoassociazioni
Nel progetto `alexandria`, ogni libro, film o videogioco è collegato ad una sua pagina in cui vengono visualizzate alcune informazioni salienti su di esso quali l'autore, la casa produttrice o simili.
Oltre alle informazioni già presenti in ciascuna pagina, si è pensato che sarebbe stato utile all'utente avere, per ogni libro, film o videogioco, anche una lista di elementi ad esso correlati, come ad esempio i sequel di un film, o altri libri ambientati nello stesso universo narrativo.
Pertanto si è deciso di inserire, per ognuna di queste tre categorie, una autoassociazione come quella in figura:
![](img/autoassociazione.png)
Un altra opzione precedentemente presa in considerazione fu quella di inserire un'unica autoassociazione, in corrispondenza dell'entità Elemento.
Questa opzione venne però scartata per ragioni di logica. L'entità Elemento, infatti, rappresenta una singola _istanza_ di un libro, film o videogioco, e sarebbe stato insensato collegare ciascuna istanza a tutte le altre, in quanto ciò avrebbe portato a un numero elevatissimo di collegamenti.

View file

@ -1,16 +0,0 @@
all: descrizione.pdf glossario.pdf autoassociazione.pdf chiaviprimarieesterne.pdf
descrizione.pdf: descrizione.md
pandoc -o descrizione.pdf descrizione.md
glossario.pdf: glossario.md
pandoc -o glossario.pdf glossario.md
autoassociazione.pdf: autoassociazione.md img/autoassociazione.png
pandoc -o autoassociazione.pdf autoassociazione.md
chiaviprimarieesterne.pdf: chiaviprimarieesterne.md img/chiaveprimariaesterna.png
pandoc -o chiaviprimarieesterne.pdf chiaviprimarieesterne.md
gerarchia.pdf: gerarchia.md img/gerarchia1.png img/gerarchia2.png
pandoc -o gerarchia.pdf gerarchia.md

View file

@ -1,38 +1,45 @@
# `alexandria`
# ![Alexandria](img/0-README/alexandria.png)
A database for an hypotetical website for users to organize and share their media library.
Un database per un ipotetico sito web di gestione libreria multimediale
Made as a collaboration between [@Steffo99](https://github.com/Steffo99/) and [@Cookie-CHR](https://github.com/Cookie-CHR) for the [Basi di Dati](http://personale.unimore.it/rubrica/contenutiad/rmartoglia/2019/58030/N0/N0/9999) exam at [Unimore](https://www.unimore.it/).
Realizzato in collaborazione tra [@Steffo99](https://github.com/Steffo99/) e [@Cookie-CHR](https://github.com/Cookie-CHR) per l'esame di [Basi di Dati](http://personale.unimore.it/rubrica/contenutiad/rmartoglia/2019/58030/N0/N0/9999) dell'[Unimore](https://www.unimore.it/).
> This project is still a work in progress!
## Specifiche
> Parts of this project may be in Italian, as the Basi di Dati course is in Italian.
Le specifiche di questo progetto sono disponibili nel file [`spec.pdf`](0-spec.pdf).
## Specification
## Capitoli della relazione
The specification for the project is available [in the `spec.pdf` file](/spec.pdf).
1. **[Descrizione](1-descrizione.md)**
2. **[Glossario](2-glossario.md)**
3. **Progettazione concettuale**
1. [Schema scheletro iniziale](3-1-schema-scheletro.md)
2. [Classificazione delle gerarchie](3-2-gerarchie.md)
3. [Identificazione delle autoassociazioni](3-3-autoassociazioni.md)
4. [Schema scheletro finale](3-4-schema-finale.md)
4. **Progettazione logica**
1. [Eliminazione delle gerarchie](4-1-eliminazione-gerarchie.md)
2. [Eliminazione delle chiavi esterne](4-2-eliminazione-chiavi-esterne.md)
3. [Trasformazione degli attributi composti](4-3-trasformazione-degli-attributi-composti.md)
4. [Dati derivati](4-4-dati-derivati.md)
5. [Schema logico](4-5-schema-logico.md)
6. [Verifica di normalizzazione](4-6-normalizzazione.md)
5. **Schema del database**
1. [Tecnologia database](5-1-tecnologia-database.md)
2. [Creazione database](5-2-creazione-database.md)
3. [Creazione tabelle](5-3-creazione-tabelle.md)
6. **[Query preprogrammate per l'utilizzo del database](6-operazioni.md)**
## Tasks
## Formati alternativi
- [x] [Descrizione](/descrizione.md)
- [x] [Glossario](/glossario.md)
- [x] [Schema scheletro](/schema-scheletro.drawio)
- [x] [Identificazione delle autoassociazioni](/autoassociazione.md)
- [x] [Identificazione delle chiavi esterne](/chiaviesterne.md)
- [ ] ...?
- [x] [Schema finale](/schema-finale.drawio)
La relazione è disponibile anche in [formato `.odt`](relazione.odt) e in [formato `.pdf`](relazione.pdf).
## Compiling
## Riproduzione del database
### Requirements
- [Pandoc](https://pandoc.org/)
- [MiKTeX](https://miktex.org/)
### Instructions
To create PDF files from the Markdown sources in this project, you can run the Makefile with the `make` command, or compile them manually with the following command:
Su una macchina con PostgreSQL 10.12 o superiore installato, eseguire in un terminale / prompt il seguente comando:
```bash
pandoc -o filename.pdf filename.md
pg_restore --dbname="alexandria" --schema="public" --file="5-database.sql"
```
> La procedura per creare una copia del database è descritta in dettaglio nel file [`5-1-tecnologia-database.md`](5-1-tecnologia-database.md).

View file

@ -1,13 +0,0 @@
# Identificazione delle chiavi primarie esterne
In `alexandria`, ogni utente potrà pubblicare una recensione riguardante un qualsiasi elemento della sua libreria (libro, film, videogioco...), con un testo e una valutazione da 0 a 100.
Le recensioni di ogni utente saranno visualizzate nella pagina del libro, film o videogioco che esse riguardano, e nella pagina del profilo dell'utente che le ha pubblicate.
Si è pensato sarebbe stato appropriato permettere alle recensioni di essere associate agli elementi della libreria di ogni utente.
![](img/chiaveprimariaesterna.png)
Essendo la relazione `riguardante` tra `Elemento` e `Recensione` una relazione _opzionale_ 1 a 1, si è deciso di utilizzare come chiave dell'entità `Recensione` l'ID (chiave primaria) dell'`Elemento` che riguarda.
Questa scelta rende semplici e veloci le interrogazioni per trovare recensioni create da uno specifico utente e recensioni riguardanti un dato libro, film o videogioco: in entrambi i casi, è richiesto l'uso di un solo `JOIN`.

View file

@ -1,14 +0,0 @@
# Aggiunta di gerarchie
Nel progetto `alexandria` sono state inserite due gerarchie:
![](img/gerarchia1.png)
Ogni utente, nel suo profilo, ha la possibilità di gestire e aggiornare una lista di elementi da lui posseduti: questi elementi possono essere libri, film o videogiochi. Siccome questi elementi hanno attributi e relazioni diverse, ma sono accomunati dall'essere posseduti dall'utente ed essere oggetto di recensioni, è sembrato opportuno rappresentarli come una gerarchia, in cui "Elemento" è l'entità padre, mentre le entità figlio sono rispettivamente "Elemento (libro)", "Elemento (film)", e "Elemento(gioco)".
![](img/gerarchia2.png)
La seconda gerarchia inserita riguarda invece le diverse edizioni di un libro: pur se relative allo stesso libro, le edizioni possono essere sia edizioni caracee (o ebook) sia edizioni audio. Le due categorie hanno attributi diversi: delle edizioni audio occorre sapere la durata in minuti, un'immagine rappresentativa e la voce narrante (che viene trattata come un'entità a parte), mentre nelle edizioni libro si vuole sapere il numero di pagine e la copertina; sono invece accomunate da tutte le altre relazioni, ad esempio l'essere relative ad uno stesso lbro.
Si è deciso di mantenere le entità di entrambe le gerarchie.

View file

@ -1,51 +0,0 @@
# Glossario
## Utenti
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Utente | username, hash della password, email, è amministratore, è bannato | user, admin, amministratore | possiede Elementi | |
## Elementi
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Elemento | stato, provenienza | | di una copia di un Libro / Film / Videogioco, posseduto da un Utente | |
## Recensioni
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Recensione | valutazione (0-100), commento, data, è nascosto | valutazione, commento, post | riguardante un Elemento | |
## Libri
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Libro | titolo originale, sinossi | testo, saggio, romanzo, opuscolo | scritto da uno o più Autori, appartenente a uno o più Generi, con più Edizioni (libro, audio), correlato ad altri Libri | |
| Genere | nome | | a cui appartengono i Libri | |
| Edizione (libro) | **isbn**, titolo localizzato, pagine, copertina | _Libro_ (ambiguo), pubblicazione, stampa | di un Libro, posseduta da più Utenti (_Elemento_), pubblicata da un Editore | |
| Edizione (audio) | **isbn**, titolo localizzato, durata, immagine | | di un Libro, posseduta da più Utenti (_Elemento_), pubblicata da un Editore, narrata da uno o più Narratori | |
| Autore | nome | scrittore | scrive dei Libri | |
| Editore | nome | | pubblica delle Edizioni (libro, audio) | |
| Narratore | nome | voce narrante | narra delle Edizioni (audio) | |
## Film
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Film | **eidr**, titolo originale, sinossi, durata, locandina | pellicola | guardato da Utenti (_Elemento_), realizzato da Cast, prodotto da Studio, appartenente a Generi, scritto da Sceneggiatori, correlato ad altri Film | |
| Genere | nome | | a cui appartengono i Film | |
| Cast | nome | "attore", "regista", "scenografo", "produttore esecutivo" | Prende parte al Film, ha un Ruolo | I ruoli sono specificati nella tabella Ruolo |
| Ruolo | nome | | di Cast | Il ruolo è un attributo! |
| Studio | nome | azienda, casa produttrice | che ha prodotto un Film | |
| Localizzazione | titolo alternativo, lingua | titolo | relativo a un Film | |
## Giochi
| Nome | Dati | Sinonimi | Collegamenti | Note |
|------|------|----------|--------------|------|
| Gioco | titolo, descrizione | videogioco, videogame | sviluppato da uno o più Studio, pubblicato da uno o più Studio, appartenente a Generi, con più Edizioni | |
| Edizioni | piattaforma, box art, titolo alternativo | | di un Gioco, giocata da Utenti (_Elemento_), portato da uno o più Studio | |
| Generi | nome | | a cui appartengono Giochi | |
| Studio | nome | | che ha sviluppato Giochi, che ha portato Edizioni | |

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
img/0-README/alexandria.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
img/3-4-relazioni/film.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
img/3-4-relazioni/libri.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1 +0,0 @@
<mxfile host="app.diagrams.net" modified="2020-04-18T17:22:44.787Z" agent="5.0 (X11)" version="12.9.14" etag="8Ng7AmxBeSFBQCzMFoPZ" type="github"><diagram id="NmbMA73EY4SfufKgQ3tE">UzV2zq1wL0osyPDNT0nNUTV2VTV2LsrPL4GwciucU3NyVI0MMlNUjV1UjYwMgFjVyA2HrCFY1qAgsSg1rwSLBiADYTaQg2Y1AA==</diagram></mxfile>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View file

@ -1,141 +0,0 @@
<mxfile host="app.diagrams.net" modified="2020-04-18T17:11:05.323Z" agent="5.0 (X11)" etag="ru7FUWLkh_5ln4O6m8-E" version="12.9.14" type="github">
<diagram id="1Sr99-bvRbM3EytH6U9A" name="Page-1">
<mxGraphModel dx="798" dy="455" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="i76pwcgAhOt-m_qU8mI_-3" value="Edizione" style="whiteSpace=wrap;html=1;align=center;strokeColor=#000000;strokeWidth=2;fontStyle=1;labelBackgroundColor=none;fontColor=#000000;labelBorderColor=none;" parent="1" vertex="1">
<mxGeometry x="364" y="570" width="100" height="55" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-4" value="Narratore" style="whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1">
<mxGeometry x="160" y="790" width="100" height="40" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-5" value="Relativa a" style="shape=rhombus;perimeter=rhombusPerimeter;whiteSpace=wrap;html=1;align=center;fontColor=#666666;strokeColor=#4D4D4D;labelBackgroundColor=none;labelBorderColor=none;" parent="1" vertex="1">
<mxGeometry x="354" y="700" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-6" value="Narrata da" style="shape=rhombus;perimeter=rhombusPerimeter;whiteSpace=wrap;html=1;align=center;" parent="1" vertex="1">
<mxGeometry x="150" y="710" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=2;fontStyle=1" parent="1" source="i76pwcgAhOt-m_qU8mI_-7" target="i76pwcgAhOt-m_qU8mI_-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-7" value="Edizione (audio)" style="whiteSpace=wrap;html=1;align=center;strokeWidth=2;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="160" y="630" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=2;fontStyle=1" parent="1" source="i76pwcgAhOt-m_qU8mI_-8" target="i76pwcgAhOt-m_qU8mI_-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-8" value="&lt;div&gt;Edizione&lt;br&gt;&lt;/div&gt;&lt;div&gt;(libro)&lt;/div&gt;" style="whiteSpace=wrap;html=1;align=center;strokeWidth=2;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="160" y="510" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-9" value="Istanza di" style="shape=rhombus;perimeter=rhombusPerimeter;whiteSpace=wrap;html=1;align=center;fontColor=#666666;strokeColor=#4D4D4D;labelBackgroundColor=none;labelBorderColor=none;" parent="1" vertex="1">
<mxGeometry x="354" y="480" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-14" value="" style="endArrow=none;html=1;rounded=0;dashed=1;dashPattern=1 2;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeWidth=1;" parent="1" source="i76pwcgAhOt-m_qU8mI_-7" target="i76pwcgAhOt-m_qU8mI_-6" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="330" y="650" as="sourcePoint" />
<mxPoint x="490" y="650" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-15" value="N" style="resizable=0;html=1;align=right;verticalAlign=bottom;" parent="i76pwcgAhOt-m_qU8mI_-14" connectable="0" vertex="1">
<mxGeometry x="1" relative="1" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-18" value="" style="endArrow=none;html=1;rounded=0;dashed=1;dashPattern=1 2;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontColor=#666666;fontStyle=1;labelBackgroundColor=none;labelBorderColor=none;" parent="1" source="i76pwcgAhOt-m_qU8mI_-9" target="i76pwcgAhOt-m_qU8mI_-3" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="330" y="650" as="sourcePoint" />
<mxPoint x="490" y="650" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-19" value="N" style="resizable=0;html=1;align=right;verticalAlign=bottom;fontColor=#000000;fontStyle=0;labelBackgroundColor=none;labelBorderColor=none;" parent="i76pwcgAhOt-m_qU8mI_-18" connectable="0" vertex="1">
<mxGeometry x="1" relative="1" as="geometry">
<mxPoint x="-14" y="-20" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-25" value="" style="endArrow=none;dashed=1;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;dashPattern=1 2;fontColor=#666666;labelBackgroundColor=none;labelBorderColor=none;" parent="1" source="i76pwcgAhOt-m_qU8mI_-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="670" as="sourcePoint" />
<mxPoint x="414" y="430" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-28" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#4D4D4D;strokeWidth=1;fontColor=#666666;exitX=1;exitY=0.5;exitDx=0;exitDy=0;labelBackgroundColor=none;labelBorderColor=none;" parent="1" source="i76pwcgAhOt-m_qU8mI_-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="330" y="650" as="sourcePoint" />
<mxPoint x="550" y="730" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-29" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#000000;strokeWidth=1;fontColor=#666666;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="i76pwcgAhOt-m_qU8mI_-4" target="i76pwcgAhOt-m_qU8mI_-6" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="350" y="780" as="sourcePoint" />
<mxPoint x="400" y="650" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-30" value="N" style="resizable=0;html=1;align=right;verticalAlign=bottom;" parent="i76pwcgAhOt-m_qU8mI_-29" connectable="0" vertex="1">
<mxGeometry x="1" relative="1" as="geometry" />
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-31" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#4D4D4D;strokeWidth=1;fontColor=#666666;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=none;labelBorderColor=none;" parent="1" source="i76pwcgAhOt-m_qU8mI_-3" target="i76pwcgAhOt-m_qU8mI_-5" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="240" y="650" as="sourcePoint" />
<mxPoint x="400" y="650" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="i76pwcgAhOt-m_qU8mI_-32" value="1" style="resizable=0;html=1;align=right;verticalAlign=bottom;fontColor=#666666;labelBackgroundColor=none;labelBorderColor=none;" parent="i76pwcgAhOt-m_qU8mI_-31" connectable="0" vertex="1">
<mxGeometry x="1" relative="1" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-2" value="" style="endArrow=none;dashed=1;html=1;startArrow=oval;startFill=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeWidth=2;" edge="1" parent="1" target="i76pwcgAhOt-m_qU8mI_-8">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="523" as="sourcePoint" />
<mxPoint x="110" y="523" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-3" value="&lt;b&gt;Pagine&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="60" y="510" width="40" height="20" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-4" value="" style="endArrow=none;dashed=1;html=1;startArrow=oval;startFill=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeWidth=2;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="550.5" as="sourcePoint" />
<mxPoint x="160" y="550" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-5" value="&lt;b&gt;Copertina&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="40" y="540" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-10" value="" style="endArrow=none;dashed=1;html=1;startArrow=oval;startFill=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeWidth=2;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="643" as="sourcePoint" />
<mxPoint x="160" y="642.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-11" value="&lt;b&gt;Durata&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="60" y="630" width="40" height="20" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-12" value="" style="endArrow=none;dashed=1;html=1;startArrow=oval;startFill=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;strokeWidth=2;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="673" as="sourcePoint" />
<mxPoint x="160" y="672.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-13" value="&lt;b&gt;Immagine&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=2;" vertex="1" parent="1">
<mxGeometry x="40" y="660" width="60" height="20" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-16" value="" style="endArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;startArrow=oval;startFill=1;strokeColor=#FF8000;" edge="1" parent="1" target="i76pwcgAhOt-m_qU8mI_-4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="800" as="sourcePoint" />
<mxPoint x="370" y="690" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-17" value="&lt;font color=&quot;#FF8000&quot;&gt;ID&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="70" y="790" width="40" height="20" as="geometry" />
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-18" value="" style="endArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;startArrow=oval;startFill=0;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="110" y="820" as="sourcePoint" />
<mxPoint x="160" y="820" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="FGvdhXYkxM2aO6fDMXdw-19" value="Nome" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="60" y="810" width="50" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

2
make_odt.sh Normal file
View file

@ -0,0 +1,2 @@
#!/bin/bash
cat 1-*.md 2-*.md 3-*.md 4-*.md 5-*.md 6-*.md | pandoc -o relazione.odt

BIN
relazione.odt Normal file

Binary file not shown.

BIN
relazione.pdf Normal file

Binary file not shown.

View file

@ -1,165 +0,0 @@
# Schema logico
Legenda:
- **Grassetto**: Chiave primaria
- → (Freccia): Chiave esterna
- _Corsivo_: Attributo opzionale
<!--TODO: Gestire le gerarchie, capire se è possibile usare il prefisso ISBN per identificare l'editore-->
## Generale
### Utente
- **Username**
- Password
- _Email_
- Amministratore
- Bannato
### Elemento
- **UUID Elemento**
- Username → Utente
- Stato
- Provenienza
### Recensione
- **UUID Elemento** → Elemento
- Commento
- Valutazione
- Data
## Libri
### Elemento (libro)
- **UUID Elemento** → Elemento
- UUID Libro → Libro
- _Stato_
- _Provenienza_
### Libro
- **UUID Libro**
- Titolo originale
- _Sinossi_
### Editore
- **Prefisso ISBN**
- Nome
### Edizione
- **ISBN Editore** → Editore
- **ISBN Resto**
- UUID Libro → Libro
- Titolo edizione
### Correlato a
- **UUID Libro 1** → Libro (UUID Libro)
- **UUID Libro 2** → Libro (UUID Libro)
### Autore
- **UUID Autore**
- Nome
### Scritto da
- **UUID Libro** → Libro
- **UUID Autore** → Autore
## Film
### Elemento (film)
- **UUID Elemento** → Elemento
- UUID Film → Film
- _Stato_
- _Provenienza_
### Film
- **EIDR**
- Titolo
- _Sinossi_
- _Durata_
- _Locandina_
### Genere
- **UUID Genere**
- Nome
### Appartiene a
- **EIDR** → Film
- **UUID Genere** → Genere
### Localizzazione
- **Lingua**
- EIDR → Film
- Titolo localizzato
### Studio
- **UUID Studio**
- Nome
### Prodotto da
- **EIDR** → Film
- **UUID Studio** → Studio
### Correlato a
- **UUID Film 1** → Film (UUID Film)
- **UUID Film 2** → Film (UUID Film)
### Ruolo
- **UUID Ruolo**
- Nome
### Cast
- **UUID Cast**
- Nome
### Ha preso parte al film
- **EIDR** → Film
- **UUID Cast** → Cast
- **UUID Ruolo** → Ruolo
## Giochi
### Elemento (gioco)
- **UUID Elemento** → Elemento
- UUID Gioco → Gioco
- _Stato_
- _Provenienza_
### Gioco
- **UUID Gioco**
- Nome
- _Descrizione_
### Edizione
- **UUID Edizione**
- UUID Gioco → Gioco
- _Titolo edizione_
- Piattaforma
- _Box art_
### Correlato a
- **UUID Gioco 1** → Gioco (UUID Gioco)
- **UUID Gioco 2** → Gioco (UUID Gioco)
### Genere
- **UUID Genere**
- Nome
### Appartiene a
- **UUID Gioco** → Gioco
- **UUID Genere** → Genere
### Studio
- **UUID Studio**
- Nome
### Portato da
- **UUID Edizione** → Edizione
- **UUID Studio** → Studio
### Sviluppato da
- **UUID Gioco** → Gioco
- **UUID Studio** → Studio
### Pubblicato da
- **UUID Gioco** → Gioco
- **UUID Studio** → Studio

View file

@ -1,16 +0,0 @@
# Tabelle
## Tabella dei volumi
| Concetto | Tipo | Volume dei dati |
|----------|------|-----------------|
## Tabella delle operazioni
| Operazione | Tipo | Frequenza |
|------------|------|-----------|
## Tabella degli accessi
| Concetto | Accessi | Tipo |
|----------|---------|------|