diff --git a/.gitignore b/.gitignore
index 86176dc..d2cb545 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
# ---> TeX
out/
+# SQLite database files
+*.db
+
## Core latex/pdflatex auxiliary files:
*.aux
*.lof
diff --git a/compitino/main.tex b/compitino/main.tex
index 4ca9dd3..6c5c6fe 100644
--- a/compitino/main.tex
+++ b/compitino/main.tex
@@ -4,6 +4,7 @@
\usepackage{enumitem}
\usepackage{forest}
\usepackage{graphicx}
+\usepackage[hidelinks]{hyperref}
\usepackage[utf8]{inputenc}
\usepackage{listings}
\usepackage{pxfonts}
@@ -11,6 +12,8 @@
\usepackage[normalem]{ulem}
\usepackage{geometry}
+\AfterEndEnvironment{figure}{\noindent}
+
\geometry{
a4paper,
top=30mm,
@@ -18,7 +21,13 @@ top=30mm,
\forestset{qtree/.style={for tree={parent anchor=south,
child anchor=north,align=center,inner sep=0pt}}}
-\lstset{upquote=true,showstringspaces=false}
+\lstset{
+ upquote=true,
+ inputencoding=utf8,
+ extendedchars=true,
+ literate={à}{{\`a}}1, % Accept à in `lstlisting` environments
+ showstringspaces=false
+}
\lstdefinestyle{SQLu}{
language=SQL,
basicstyle=\small\ttfamily,
@@ -34,17 +43,22 @@ top=30mm,
% First page information
-\title{\textbf{Basi di dati prof. Ghelli}\linebreak\textit{``Sempre sul pezzo"}}
+\title{\textbf{Basi di dati prof. Ghelli}\linebreak\textit{``Una cervecita fresca"}}
\author{Davide Testa 613565}
-\date{2020-05-15}
+\date{2020-06-01}
\begin{document}
\maketitle % Insert the title, author and date
+ \input{\folder/source_code.tex}
\section{Descrizione di massima del dominio (testo)}\label{sec:testo}
\input{\folder/testo.tex}
+ \clearpage
\section{Descrizione del dominio}\label{sec:dominio}
\input{\folder/dominio.tex}
+% \clearpage
\section{Schema concettuale}\label{sec:schema-concettuale}
+ La figura~\ref{fig:schema-concettuale} mostra lo schema concettuale in formato
+ grafico.
\begin{figure}[hb]
\centering
\includegraphics[width=\linewidth]{\folder/schema_concettuale.pdf}
@@ -52,11 +66,14 @@ top=30mm,
\label{fig:schema-concettuale}
\end{figure}
\input{\folder/schema_concettuale.tex}
- \section{Schema logico}\label{sec:schema-logico}
+ \clearpage
+ \section{Schema logico relazionale}\label{sec:schema-logico}
+ La figura~\ref{fig:schema-logico} mostra lo schema logico relazionale in
+ formato grafico.\\
\begin{figure}[htb]
\centering
\includegraphics[width=\linewidth]{\folder/schema_logico.pdf}
- \caption{Schema logico in formato grafico}
+ \caption{Schema logico relazionale in formato grafico}
\label{fig:schema-logico}
\end{figure}
\input{\folder/schema_logico.tex}
@@ -66,4 +83,6 @@ top=30mm,
\vskip2pc
\section{Piani di accesso}\label{sec:piani}
\input{\folder/piani_di_accesso.tex}
+ \vfill
+ \input{\folder/source_code.tex}
\end{document}
diff --git a/compitino/secondo_compitino/dominio.tex b/compitino/secondo_compitino/dominio.tex
index 17aef8d..10f93e5 100644
--- a/compitino/secondo_compitino/dominio.tex
+++ b/compitino/secondo_compitino/dominio.tex
@@ -1,5 +1,75 @@
% !TEX root = ../main.tex
-Descrizione del dominio.
+L'applicazione ``Una cervecita fresca" deve fornire supporto ai birrai e alle
+birraie artigianali nella produzione delle loro birre fatte in casa con il
+metodo all-grain.
-Nominare le classi di interesse, specificarne gli attributi e indicarne le relazioni con le altre classi.
\ No newline at end of file
+Ogni utente dell'app (birraio o birraia) può lavorare per uno o più birrifici, e può
+visualizzare le ricette dei birrifici per cui lavora.
+Del birraio o birraia sono rilevanti il nome, il cognome, il soprannome,
+l'indirizzo email, il codice fiscale.
+Ogni birrificio ha un nome, un anno di fondazione, un motto e uno stemma.
+Il birrificio ha inoltre una capacità produttiva, cioè il numero massimo di
+litri che può produrre in un singolo ciclo produttivo.
+Per ogni birrificio possono lavorare più persone.
+Ogni birrificio può lavorare a una sola produzione per volta, mettendo a
+disposizione tutta la sua capacità produttiva, o solo una parte di questa.
+
+Ogni birrificio ha accesso a una o più ricette: ogni ricetta ha un nome, un
+creatore o creatrice, una data di creazione, una eventuale ricetta madre
+(ovvero la ricetta che è stata modificata per elaborarla) e la quantità
+relativa di ciascun ingrediente.
+Oltre alla creatrice o creatore di una ricetta, anche le birraie e i birrai di
+un birrificio possono vedere le ricette del birrificio in cui lavorano.
+La ricetta può essere archiviata o eliminata dal creatore o creatrice: lo stato
+della ricetta può essere attiva, archiviata, eliminata.
+
+Gli ingredienti sono moltissimi, ma di solo 5 tipi: malti, luppoli, lieviti,
+zuccheri e additivi.
+Ciascun tipo ha un nome e la sua unità di misura appropriata (per esempio, i
+luppoli vengono espressi in \textit{mash}, ovvero grammi per litro di
+miscuglio, mentre i malti sono espressi in peso percentuale sugli ingredienti
+secchi).
+Ciascun ingrediente ha un tipo e una descrizione.
+In ogni ricetta, è indicata la quantità di ciascun ingrediente come numero
+puro: l'unità di misura (mash, peso percentuale, \textellipsis) dipende dal
+tipo di ingrediente.
+La quantità di acqua è ricavabile dagli altri ingredienti e non occorre quindi
+memorizzarla: si miscelano in proporzione gli ingredienti secchi, dal
+\textit{mash} si capisce quale volume finale deve raggiungere la soluzione.
+
+La visualizzazione delle ricette terrà conto della quantità di prodotto che si
+vuole produrre (che dev'essere inferiore o uguale alla capacità produttiva del
+birrificio) per mostrare le quantità assolute dei vari ingredienti in kg e L;
+nel database invece le quantità verranno memorizzate in termini relativi come
+descritto sopra.
+
+Una produzione è caratterizzata da una data di produzione, un numero di lotto
+che la identifica univocamente, il numero di bottiglie da 500 mL prodotte
+(questo è l'unico possibile formato di produzione) e uno stato di preparazione
+(in corso, completa, annullata).
+È prodotta seguendo una ricetta di un birrificio.
+
+A ogni produzione si possono accompagnare alcune note.
+Ogni nota ha un testo.
+Esistono particolari note, dette di degustazione, che esprimono anche un
+giudizio da 1 a 10 sulla qualità del prodotto.
+
+Il birrificio tiene un registro degli acquisti, conservando i dati della
+fattura e specificando per ogni ingrediente acquistato la quantità.
+Ogni fattura registrata dal birrificio è caratterizzata da una data, un numero
+di fattura, un importo e un fornitore.
+I fornitori hanno una ragione sociale, una partita IVA e un indirizzo.
+L'inventario mostra, per ogni ingrediente, la quantità disponibile e quella
+totale (compresi cioè gli ingredienti ``prenotati" da preparazioni in corso).
+
+Oltre che come birrario o birraia, ci si può anche registrare come cliente,
+specificando un indirizzo di spedizione.
+I clienti sono caratterizzati, come chi produce birra, da nome, cognome, email
+e codice fiscale, ma non hanno un soprannome.
+
+La clientela può effettuare prenotazioni per una quantità di bottiglie di un
+dato lotto di produzione.
+Ogni prenotazione ha uno stato, che rimane in sospeso fino al termine della
+produzione, quando il birrificio può impostarlo su `confermato' se intende
+procedere alla vendita oppure `annullato' se il prodotto non è soddisfacente.
diff --git a/compitino/secondo_compitino/piani_di_accesso.tex b/compitino/secondo_compitino/piani_di_accesso.tex
index 3ae00b9..e1f2fda 100644
--- a/compitino/secondo_compitino/piani_di_accesso.tex
+++ b/compitino/secondo_compitino/piani_di_accesso.tex
@@ -3,33 +3,35 @@
\paragraph{Piano di accesso logico della query a}
\begin{center}
- \begin{forest}
- [{$\pi^{b}$ R.C, S.D}
- [{$\bowtie$ R.E = S.F}
- [{$\sigma$ C $>=$ 10}
- [Tabella1 R]
+ \begin{forest}, baseline, qtree
+ [{$\pi^{b}$ r.IdRicetta , r.Nome}
+ [{$\bowtie$ p.IdPersona = r.IdCreatrice}
+ [{$\sigma$ p.Nome = 'Giovanni'}
+ [Persone p]
]
- [Tabella2 S]
+ [Ricette r]
]
]
\end{forest}
\end{center}
+Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
+duplicati.
\paragraph{Piano di accesso fisico della query a senza indici}
\begin{center}
- \begin{forest}
- [{Project(\{C, D\})}
- [{SortMerge(R.E = S.F)}
- [{Sort(\{E\})}
- [{Project(\{E, C\})}
- [{Filter(C $>=$ 10)}
- [{TableScan(Tabella R)}]
+ \begin{forest}, baseline, qtree
+ [{Project(\{r.IdRicetta , r.Nome\})}
+ [{SortMerge(p.IdPersona = r.IdCreatrice)}
+ [{Sort([p.IdPersona])}
+ [{Project(\{p.IdPersona\})}
+ [{Filter(p.Nome = 'Giovanni')}
+ [{TableScan(Persone p)}]
]
]
]
- [{Sort(\{F\})}
- [{Project(\{C, F\})}
- [{TableScan(Tabella S)}]
+ [{Sort([r.IdCreatrice])}
+ [{Project(\{r.IdRicetta, r.Nome, r.IdCreatrice\})}
+ [{TableScan(Ricette r)}]
]
]
]
@@ -40,12 +42,210 @@
\paragraph{Piano di accesso fisico della query a con due indici}
\begin{center}
\begin{forest}, baseline, qtree
- [{Project(\{C, D\})}
- [{IndexNestedLoop(R.E = S.F)}
- [{IndexFilter(Tabella R,\\ IndRC, C $>=$ 10)}]
- [{IndexFilter(Tabella S,\\IndSF, S.F = R.E)}]
+ [{Project(\{r.IdRicetta , r.Nome\})}
+ [{IndexNestedLoop(p.IdPersona = r.IdCreatrice)}
+ [{IndexFilter(Persone p,\\ IndPN, p.Nome = 'Giovanni')}]
+ [{IndexFilter(Ricette r,\\IndRC, r.IdCreatrice = p.IdPersona)}]
]
]
\end{forest}
\end{center}
-Indici necessari: \texttt{IndRC} (indice della tabella R sull’attributo C) e \texttt{IndSF} (indice della tabella S sull'attributo F).
\ No newline at end of file
+Indici necessari: \texttt{IndPN} (indice della tabella Persone sull’attributo
+Nome) e \texttt{IndRC} (indice della tabella Ricette sull'attributo Creatrice).
+
+\clearpage
+\subsection{Query b}
+
+\paragraph{Piano di accesso logico della query b}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{$\tau$[-DiversiFornitori]}
+ [{$\pi^{b}$ fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori}
+ [{$\sigma$ COUNT(DISTINCT fa.IdFornitore) $>=$ 3}
+ [\{fa.IdBirrificio\} {$\gamma$ \{COUNT(DISTINCT fa.IdFornitore)\}}
+ [{$\sigma$ fa.Data $>=$ '2020-01-01'}
+ [Fatture fa]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+
+Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
+duplicati, in quanto la GROUP BY raggruppa per IdBirrificio.
+\paragraph{Piano di accesso fisico della query b senza indici}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{Sort[-DiversiFornitori]}
+ [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
+ [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
+ [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
+ [{Sort([fa.IdBirrificio])}
+ [{Filter(fa.Data $>=$ '2020-01-01')}
+ [{TableScan(Fatture fa)}]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+Il sort sull'attributo dimensione di analisi prima della GroupBy è necessario,
+in quanto non è garantito che i record della tabella Fatture siano raggruppati
+per IdBirrificio.
+Lo sarebbero se l'organizzazione primaria della tabella fosse sequenziale
+proprio su questo attributo, il che è estremamente poco probabile.
+\clearpage
+\paragraph{Piano di accesso fisico della query b con un indice}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{Sort[-DiversiFornitori]}
+ [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
+ [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
+ [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
+ [{Sort([fa.IdBirrificio])}
+ [{IndexFilter(Fatture fa, IndFD, fa.Data $>=$ '2020-01-01')}]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+Indice necessario: \texttt{IndFD} (indice della tabella Fatture sull’attributo
+Data).
+Il sort sull'attributo IdBirrificio prima della GroupBy è necessario, in quanto
+i record in input sono ordinati per data, il che non ci garantisce che siano
+raggruppati per IdBirrificio (che è dimensione di analisi).
+
+\subsection{Query c}
+
+\paragraph{Piano di accesso logico della query c}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{$\pi^{b}$ fo.RagioneSociale, SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio}
+ [$\sigma$ SUM(fa.Importo) $>$ 10
+ [{\{fo.IdFornitore, fo.RagioneSociale\} $\gamma$ \{SUM(fa.Importo), AVG(fa.Importo)\}}
+ [{$\bowtie$ fa.IdFornitore = fo.IdFornitore}
+ [{Fornitori fo}]
+ [{$\bowtie$ fa.IdBirrificio = b.IdBirrificio}
+ [{$\sigma$ b.Nome = 'Pirati Rossi'}
+ [{Birrifici b}]
+ ]
+ [{Fatture fa}]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+
+In questo caso non ci dovrebbe essere differenza tra $\pi^{b}$ e $\pi$: non ci
+devono essere due fornitori con la stessa ragione sociale (la ragione sociale
+è chiave naturale); è comunque possibile un errore di inserimento se non ho
+impostato un vincolo di unicità anche su questo attributo, che non ho scelto
+come chiave primaria della tabella: ecco perché ho raggruppato anche per
+IdFornitore e non solo per RagioneSociale.
+
+Ho scelto l'ordine di giunzione in modo da avere la restrizione il più distale
+possibile.
+
+\clearpage
+
+\paragraph{Piano di accesso fisico della query c senza indici}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
+ [{Filter(SUM(fa.Importo) $>$ 10)}
+ [{GroupBy(\{fo.IdFornitore,fo.RagioneSociale\}, \{SUM(fa.Importo), AVG(fa.Importo)\})}
+ [{MergeSort(fa.IdFornitore = fo.IdFornitore)}
+ [{Sort([fo.IdFornitore])}
+ [{Project(\{fo.IdFornitore,\\fo.RagioneSociale\})}
+ [{Fornitori fo}]
+ ]
+ ]
+ [{Sort([fa.IdFornitore])}
+ [{Project(\{fa.IdFornitore, fa.Importo\})}
+ [{MergeSort(fa.IdBirrificio = b.IdBirrificio)}
+ [{Sort([b.IdBirrificio])}
+ [{Project(\{b.IdBirrificio\})}
+ [{Filter(b.Nome = 'Pirati Rossi')}
+ [{TableScan(Birrifici b)}]
+ ]
+ ]
+ ]
+ [{Sort([fa.IdBirrificio])}
+ [{Project(\{fa.IdBirrificio,\\fa.IdFornitore fa.Importo\})}
+ [{Fatture fa}]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+Non è necessario ordinare per \texttt{[fo.IdFornitore, fo.RagioneSociale]} prima
+della GroupBy: per costruzione, l'ordine dell'operatore esterno della SortMerge
+viene mantenuto nell'output, e questo ordine è sull'attributo fo.IdFornitore,
+che a sua volta determina funzionalmente l'altra dimensione di analisi, fo.RagioneSociale.
+
+Pertanto, è garantito che l'input della GroupBy sarà già raggruppato per gli
+attributi che sono dimensione di analisi e non occorre un ordinamento
+preventivo.
+
+\clearpage
+\paragraph{Piano di accesso fisico della query c con tre indici}
+\begin{center}
+ \begin{forest}, baseline, qtree
+ [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
+ [{Filter(SUM(fa.Importo) $>$ 10)}
+ [{GroupBy(\{fo.IdFornitore, fo.RagioneSociale\},\\\{SUM(fa.Importo), AVG(fa.Importo)\})}
+ [{Sorted([fo.IdFornitore])}
+ [{Project(\{fo.IdFornitore, fo.RagioneSociale, fa.Importo\})}
+ [{IndexNestedLoop(fa.IdFornitore = fo.IdFornitore)}
+ [{IndexNestedLoop\\(fa.IdBirrificio = b.IdBirrificio)}
+ [{IndexFilter(Birrifici b, IndBN,\\b.Nome = 'Pirati Rossi')}]
+ [{IndexFilter(Fatture fa, IndFaIdB,\\fa.IdBirrificio = b.IdBirrificio)}]
+ ]
+ [{IndexFilter(Fornitori fo, IndFoIdF,\\fo.IdFornitore = fa.IdFornitore)}]
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ \end{forest}
+\end{center}
+Indici necessari: \texttt{IndBN} (indice della tabella Birrifici sull’attributo
+Nome), \texttt{IndFaIdB} (indice della tabella Fatture sull'attributo
+IdBirrificio) e \texttt{IndFoIdF} (indice della tabella Fornitori sull'attributo
+IdFornitore).
+
+Occorre ordinare per IdFornitore prima della \texttt{GroupBy}, in quanto
+l'output della IndexNestedLoop è ordinato come l'operatore esterno, ovvero
+per nome del birrificio.
+
+Potrei spostare l'ordinamento tra le due giunzioni con IndexNestedLoop, tanto
+ogni fattura ha un fornitore e l'output non andrà a decrecere dopo la seconda
+giunzione (anzi, si arricchirà di campi).
+Il sort andrebbe fatto con il minor numero possibile di dati, dato l'alto costo
+dell'algoritmo, eliminando i campi superflui con una project prima.
+
+Il vantaggio dell'IndexNestedLoop sul SortMerge si ha solo se la condizione è
+sufficientemente restrittiva da essere soddisfatta da una piccola minoranza
+di record.
+In questo caso, la restrizione sul nome del birrificio dovrebbe essere
+abbastanza restrittiva (se ci sono abbastanza birrifici, il numero di
+birrifici con il nome `Pirati Rossi' sarà trascurabile rispetto al totale) ed
+è ragionevole che le fatture che riguardano quel birrificio siano una esigua
+minoranza rispetto al totale delle fatture.
+Se così non fosse, pur avendo i tre indici a disposizione, converrebbe
+utilizzare comunque il SortMerge.
diff --git a/compitino/secondo_compitino/queries.tex b/compitino/secondo_compitino/queries.tex
index 6a98470..b76c379 100644
--- a/compitino/secondo_compitino/queries.tex
+++ b/compitino/secondo_compitino/queries.tex
@@ -1,14 +1,122 @@
% !TEX root = ../main.tex
\begin{enumerate}[label=\alph*.]
- \item Uso di proiezione, join e restrizione
+ \item Uso di proiezione, join e restrizione.
- Per ogni record di R con valore di C maggiore o uguale a 10 e che ha un valore di E uguale a un valore di F nella tabella S, riportare R.C e S.D.
-\begin{lstlisting}[style=SQLu]
-SELECT R.C, S.D
-FROM Tabella1 R
-JOIN Tabella2 S ON R.E = S.F
-WHERE R.C >= 10
+ Mostrare l'IdRicetta e il Nome delle ricette create da birrai di nome
+ Giovanni.
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT r.IdRicetta, r.Nome
+FROM Ricette r
+JOIN Persone p ON p.IdPersona = r.IdCreatrice
+WHERE p.Nome = 'Giovanni'
+\end{lstlisting}
+ \item Uso di group by con having, where e sort.
+
+ Per ogni birrificio che abbia fatto almeno un acquisto quest'anno,
+ riportare l'IdBirrificio e il numero di diversi fornitori da cui ha
+ acquistato quest'anno, se questo numero è almeno di 3.
+ Ordinare il risultato dal birrificio che ha avuto più fornitori a quello
+ che ne ha avuti meno.
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT fa.IdBirrificio,
+ COUNT(DISTINCT fa.IdFornitore) DiversiFornitori
+FROM Fatture fa
+WHERE fa.Data >= '2020-01-01'
+GROUP BY fa.IdBirrificio
+HAVING COUNT(DISTINCT fa.IdFornitore) >= 3
+ORDER BY COUNT(DISTINCT fa.IdFornitore) DESC
+\end{lstlisting}
+ \item Uso di join, group by con having e where.
+
+ Dei fornitori da cui ha ordinato il birrificio `Pirati Rossi', mostrare la
+ ragione sociale, l'importo totale e l'importo medio delle fatture, purché
+ l'importo totale sia superiore a 10 euro.
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT fo.RagioneSociale, SUM(fa.Importo) ImportoTotale,
+ AVG(fa.Importo) ImportoMedio
+FROM Fornitori fo
+JOIN Fatture fa ON fa.IdFornitore = fo.IdFornitore
+JOIN Birrifici b ON b.IdBirrificio = fa.IdBirrificio
+WHERE b.Nome = 'Pirati Rossi'
+GROUP BY fo.IdFornitore, fo.RagioneSociale
+HAVING SUM(fa.Importo) > 10
+\end{lstlisting}
+ \item Uso di select annidata con quantificazione esistenziale.
+
+ Mostrare il soprannome de* birrai* che siano aut*r* di almeno una ricetta.
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT b.Soprannome
+FROM Birraie b
+WHERE EXISTS (SELECT *
+ FROM Ricette r
+ WHERE r.IdCreatrice = b.IdPersona)
+\end{lstlisting}
+\clearpage
+
+ \item Uso di select annidata con quantificazione universale.
+
+ Mostrare il nome e il cognome de* clienti che hanno ordinato da un solo
+ birrificio.
+
+\textbf{Traduco in notazione insiemistica:}
+\begin{lstlisting}[style=SQLu,escapechar=@]
+{p1.Nome, p1.Cognome | (p1 @$\in$@ Persone, pre1 @$\in$@ Prenotazioni,
+ pre1.IdCliente = p1.IdPersona,
+ pro1 @$\in$@ Produzioni,
+ pro1.IdProduzione = pre1.IdProduzione,
+ r1 @$\in$@ Ricette,
+ r1.IdRicetta = pro1.IdRicetta) .
+ @$\forall$@ (pre2 @$\in$@ Prenotazioni, pre2.IdCliente = pre1.IdCliente
+ pro2 @$\in$@ Produzioni, pro2.IdProduzione = pre2.IdProduzione,
+ r2 @$\in$@ Ricette, r2.IdRicetta = pro2.IdRicetta) .
+ (r2.IdBirrificio = r1.IdBirrificio)}
+\end{lstlisting}
+
+\textbf{Sostituisco il $\forall x . P$ con $\neg\exists x . \neg P$}
+\begin{lstlisting}[style=SQLu,escapechar=@]
+{p1.Nome, p1.Cognome | (p1 @$\in$@ Persone, pre1 @$\in$@ Prenotazioni,
+ pre1.IdCliente = p1.IdPersona,
+ pro1 @$\in$@ Produzioni,
+ pro1.IdProduzione = pre1.IdProduzione,
+ r1 @$\in$@ Ricette,
+ r1.IdRicetta = pro1.IdRicetta) .
+ @$\neg\exists$@ (pre2 @$\in$@ Prenotazioni, pre2.IdCliente = pre1.IdCliente
+ pro2 @$\in$@ Produzioni, pro2.IdProduzione = pre2.IdProduzione,
+ r2 @$\in$@ Ricette, r2.IdRicetta = pro2.IdRicetta) .
+ (r2.IdBirrificio @$\neq$@ r1.IdBirrificio)}
+\end{lstlisting}
+
+ \textbf{Scrivo quindi la query}, inserendo l'IdPersona e la parola chiave
+ \texttt{DISTINCT} per rimuovere i duplicati (ma non le persone omonime).
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT DISTINCT p1.IdPersona, p1.Nome, p1.Cognome
+FROM Persone p1
+JOIN Prenotazioni pre1 ON pre1.IdCliente = p1.IdPersona
+JOIN Produzioni pro1 ON pro1.IdProduzione = pre1.IdProduzione
+JOIN Ricette r1 ON r1.IdRicetta = pro1.IdRicetta
+WHERE NOT EXISTS (SELECT *
+ FROM Prenotazioni pre2
+ JOIN Produzioni pro2
+ ON pro2.IdProduzione = pre2.IdProduzione
+ JOIN Ricette r2 ON r2.IdRicetta = pro2.IdRicetta
+ WHERE pre2.IdCliente = pre1.IdCliente
+ AND r2.IdBirrificio <> r1.IdBirrificio)
+\end{lstlisting}
+
+ \item Uso di subquery di confronto quantificato.
+
+ Per ogni birrificio, mostrare l'IdBirrificio e l'ultimo NumeroLotto
+ prodotto in quel birrificio (sapendo che il NumeroLotto è progressivo).
+\begin{lstlisting}[style=SQLu,escapechar=@]
+SELECT r1.IdBirrificio, pro1.NumeroLotto
+FROM Produzioni pro1
+JOIN Ricette r1 ON r1.IdRicetta = pro1.IdRicetta
+WHERE pro1.NumeroLotto >= ANY (SELECT pro2.NumeroLotto
+ FROM Produzioni pro2
+ JOIN Ricette r2
+ ON r2.IdRicetta = pro2.IdRicetta
+ WHERE r2.IdBirrificio = r1.IdBirrificio)
\end{lstlisting}
\end{enumerate}
\clearpage
\ No newline at end of file
diff --git a/compitino/secondo_compitino/schema.drawio b/compitino/secondo_compitino/schema.drawio
index 4ff91ba..d4b5c1e 100644
--- a/compitino/secondo_compitino/schema.drawio
+++ b/compitino/secondo_compitino/schema.drawio
@@ -1 +1 @@
-7V1tc9q4Fv41mdl7Z7KDX8DwkZC2l7lpt9O0m493FKyAdm2La4sk5NevDBLYPgIcbCMT1Om0QRaKdZ7zpnOOpCtnFL5+idF89pX6OLiyO/7rlXN7Zdu25Vn8v7RluW7pu866YRoTf91kbRvuyRsWjR3RuiA+TtZtoolRGjAyT3LfntAowhOWa0NxTF/y3Z5okP+tczTFoOF+ggLY+kB8NhOzsL1t+38wmc7kb7Z6g/WTEMnO4rWTGfLpS6bJ+XTljGJK2fqn8HWEg5R4ki7r733e8XTzYjGOWJkvvHYT7+b1zSO3Y/Q0/vN/aP5Mri2BRsKWcsbY5wQQH2nMZnRKIxR82rbexHQR+TgdtsM/bfvcUTrnjRZv/AszthRoogWjvGnGwkA8xZE/TLHhHyMa4XXLZxIEYkg4NTHbhC7iCd4zn65gERRPMdvTT4CUzjXzCwThvmAaYhYveYcYB4iR5zwzIMFT000/8VU+KbTMdJhTErEkM/L3tIF3EOJxLXljKcWlAGGhv+Xt7c9/WL+B/JSZyrZpxRbvYRFB02cULAQdIM8EARfIFMiXGWH4fo5WKL1wnZBHHiXztZQ+kdeUg26eOOojGtB4NZDTWf3ZxwLPOGb4dS9o4mmvQKyO+PyylWNJ/1lGhGWbCuUMpY8gpHeYkFxJzNMfnwL8KkQkKy2TACUJmeRpery0WGXFxSopLhnSdhWklW3vkyooBlYeWWtQgGw9cfGtffJUYBGnUxhoTRgwUF2iBSXrC6Ex16QEMsYLCQO00pVPNGJSQaf4T2Yk8O/Qki5SMicMTf6Wn25mNCZvvD+SzMIfx0woZruX63GfflNo4BgnvM93yVNWoekres11vEMJEw0TGgRonpDHzfuFnIgkuqGM0VB04jOcRik/87FwLOe0fivLrUf8r61OQQF4NlAAGw7IsandkAaACmBEw0XEDSsK5whgzifKVpDF9G8slaQwmFm9KZoSrnVJNL3DT+k83G3LDzG1tIlyAj4FK2UyI76Po5U9Z4ihNWApOsJs8Xfo3vC/nEKjzu/dqy5/pxH/bG0/879p95iNaMRfE5EVWphzwwtOOSKHq63Eda9gHAZbYtsrB63sVzu0AwDtPWHkAT8aSa4syYO2ybFlAbR/xYGRXyAN5yO/ENFPPnkjNDKmuBZTnJNgF3riSrStjtsQ3DaA+ydhXByNDAOJOB8ZdgCotyTGnNdjbHA9HldpRrXh6gJch1FEP9PIR6mGNuBWANfr6za8fYAuN2yMrJF1hvyRT5IpWXC7mIYg0nAFJ3uwE/VstKlo21K6kAkKhuJByJFchzRT27kTyRSsNIqZCEDqsordvF9rK8yid8oIlQxI7Q31ZcLDfO6ELX+sojk0yoaIi+yrDv5++vGGY/qTfkXRUjpE22chivw/VgK6k9iHI1xXJQNcZQPCWWw6SpelphhXt+Ay9Y6McdmFgZziQA3HuBzoWTfMU1xv7GIpyG4i61AxjjooyWZSi7aGzdyiZ34sm3UtzWzm7eUqYekrZ67ew085ptwqs7pSXY5dt24rzUvVvDl3L1INpRyVwK0B2YtbDuEtdNX0hdMvCZ3EuC3Q9XRA11y22C2LQ7dsAqzZfHHXeV++2NufX24mX+yWSHO2M19cMGHaE8ZdGNC4kKVR12nb0qgLgxCAyqdN3ks5a8TpbDB731frpHd7nIVxrG4hVtx07h6ua2TyPmHkc4zxHYomUBRN9uDdermoDLTn/+TARcXM0PjZpPEVMnI+OQQXhiMzYn1L5lyhpyEKI9eV5dp12ybXLqziGFGfTPA4midGrqGQnI9cy4HVcm2kubrL7hYiifpz/HAh+m0R4pgOg0eT6FeIxhlJM7TSIzqN+OgG1wq4as/029AAfzOgVgNVe4ZfBrEzoP5JEsLM2ri61bWLO4JUgbKT+tAODJT9xOGc3mHGFrFZHSvk4nzsrgX18zANG1OzY6UJYfZKutBOU1FvG2YgTJ3sLpk4HzG2oY6+T5mdGWyrYqvfhYabCm85Vb8vHh8DMjEFs5UR1u5Py8hKNvsQ45AsQoNrBVw3gShtwHoQWIBouSJIiWe26OkxoKmzpCp3qqWYplf67AUxq9YUQV4Xixctu1PAuGxS+rpYUGlZxaEazkt7kGcaL4TMsluGlzIMKZmvrgq6fq9uZjtNBZ2n5byVsnqgoTK7ftkyu37ZSpXTgLWxCB9blqSNOwiP1PCtgad7EfA4ZwrP5uCrDw2PV1q5tcsSWdJD/tjw9Msqt9bBcxHKzeqUrWJtmSNnWfv3QlwcPvrk5yH+MnUDezh++TWa/Pfhr/jp/8vNiRMNw1Nqj1ftmxCVMy69ImoXTtbpxUixRVQtTRW37VWCSe4RawtOH80cqWdpl/W1nXah89GMUTV0+u2SHVh6Onx85IQPTSF5E+fDuYp9e8pAvly61Q44LDxNU3D3E+Tj6O1CS2D2SkYrU+fKN4aFpytoU5ZPJjG54PRqPQBrz587EOFfzCjqWhS1U9iP7vTLVjg1tknAMRXHh8oUz2+zjwv35prtAdVx1a6bXRvgOo58wrXlm6laq4Ks9pqmvrG6zZ2+6wyKNSnyEh59lcWWogZ17K8wvwglneVdt6Rc98/PEveNe1U7qNrN8ADWKRr3qjqu2o3wALrNxr2qA1n9pcUye242bp3Ew/JKn34g0+b1Iw496rEvML8IaT7Gw9qIyfl4WAPoYY19cXcJ/vclAN0YtvodLbP9sgFY9ftZZvtlU9i2wNMy+y8bhtgp6Vs1BzEs6DAbMGsAtqvbl+pB2TW3wNW3SuoVrtv1eiUBby4MPYClOlvv+RKk+ZhVUu/8rmftQZVtPOnKsGpfIPUUlXbmyr8akNW+RurB8JW59K82ePUvk3owhyTP4zWuVnVXyyu4WgOvZMa/jproHTvJFNmlywpUHuVrdUpj3xpfC+aaRjRcRJgLWTi/0PL3msDV73HBkPQ9YeQBPxq1XV1td732qW0IuFHbhyXbKY19a9Q2zEr8ioNLALgxTLVr6z4Me5ijt+tS1sWij9LKusmqWpW2XkF+EX7XUVW1rd6EuANm1VpKFvdchFFuDFz9OhvGNM0B+jWBqz2sadlwcSy3PRi5rQLtSUOae4+nMOc8nGp5fOKNTGrUVXW2FyTQB1yu/ZLSSpdL/cr7CgUM0LUBfUr3S/3KMAxymSd8nAbvU3pk6leGK2ZzWE9N4OpPM3t7r3M2t7TX6JzZ+ducLcvSnrtQ+mZb/JGx24fEppUOmvqV4T4oLjyMMDR+vlAtXhO0+iNiu2uFuBK/JXMc+WaJXZMWB/fXtECNq9ZeRo2XiKKdX/FQX3V0l08meBzNk0vAuTFo9atxGB/NqHGjvKsrb6twvuLA1b7BZnP92S7lfQkyfZTubnWMVP3KMJTybRHimA6DR7PRpgq0+nU3jIqaI5+q46o9H92HO17N+WwVQdUf9dzc2qM47sm4XI26XN5A+3K5s+/kJ7NWPigz5+NwWR3V4U8mMtII2voz0xBsAG/21p80JMqWP1ZX3NAoe6Hw8ZeIH3EjVva2HuW8HAFFe+4Dd/M63S2ujg/eBr7ri/Xd/a2kpA0D5YBDymGvuqXuwMVPOxng4L1Opa86a5wBJG7d9wK+5ZzfOx3Ltftdb/VvL89IxXGb5gfoBh7ND+DKvMP3gNXDHGXvKzwZc3h1MUcnnzEHAzfNHdBPrKgt/oAG4yB3VLsSzil7Y/zJuMNqijuKAzfMHQ6MDIxQ7JPUs2RXI+dq2AHcIpzLDJOANVjqb5EJCobiQcgdxpVPslrj7XQYU58wvY8wEbxY0+qtULPiyKxKhls8lYvXVDGxA4Plv6WusvWvs6d1Ia+suqTPPSmpoW38zfqYpLZ1kxoamhVXRx+P1Ipzv09LarhGXHH1ByR1rzFS848xpSxrT2M0n32lPk57/AM=
\ No newline at end of file
+7V1tc9u2sv41num5M/YQ4PvHxIlzPCdOe+xkevqRkRgZrUSqFNXE+fUXlAiK4kIiJBAEaaHTaS1KoiQ8u9hnF/tyZd8ufnzIouXzQzqN51fYmv64st9dYYxsz6X/K668bK/Y2NtemGVkWr5od+GJ/IzLi1Z5dU2m8Wp7rbyUp+k8J8vV3rsnaZLEk3zvWpRl6ff9l31L5/ufuoxmMbjwNInm8OrvZJo/b68G2N9d/3dMZs/sk5EXbp9ZROzF5ddePUfT9Hvtkv3+yr7N0jTf/rX4cRvPi8Vj67J9392BZ6svlsVJLvKGt0v7p/32ze9vn35+CL9kNnn8++XaKeFZ5S/sF8dTugDlwyRN6P/eZuk6mcbFfSz6KM3y53SWJtH8Y5ou6UVEL/4Z5/lLCV+0zlN66TlfzMtnV3mU5W8KOOiF948/4yz9nD5EyQt77o7M2WvjZLp75SJKpr9uvgO9XL7I2j4qP8yjj+gdZnH+W5yRRZzH2dMympBkVr50lWfpXxV4xSfAlSsXc5Wus0l8ZLlQUIrg5gOPvLAUj2Ita59QAvMhTun3zF7oC7J4HuXkn31hi0qZnVWv28FK/yiRPQFl7zjKO0Df764a0KvVQ4Kgu3hYqAf963Z50zq81j68X+fp5K/BQOsJQstkYCDQ+p7Ztk+BORSEGdmDgjmwzb7dA+r+sKy1HxrlPgFmht7IOFmAAcoG0lMhDaxBYYosR/uG3c7Ayld0iDQFOHv5X/H0jcse/lHdmD5492Pv0Uv5SMIRExSQsHNKvnkrXcropfaCZUqSfFW782/FBfqCMg5yzYIAZRQEOw1fHb7+6BvoH9uvsJPV6rdIiO/2I/+J5mu29oR+ComBUK++k8U82ojRtzTJmXwXsjB5JvPpx+glXRe4UDGc/MUevX1OM/KTvj7ak9xS7rC394qn4p2lnGTxir7mNyYnqHHpIfqx98KP0SovL0zS+TxarsjX6vstqMiQ5G2a5+mifFE0J7OE/j2h94oz9pu23wo5x+T0nzjL4x9HBYsh6u4Dyh5+3wWVkFdee64FlJhP2fle5QCwn9JlFiUJvT/Am/7IvNL823SeZrt95BvdRBqXVtv94mP8rfgVzu7KY/nDikspXbxv882O9Eym0zjZbIV5lEdbsApkSr2i38F9S/+l63NbbDEu/U639DHaPab/Fi/P8ts0oV8zIhukYioJ3+NCGvYwxVxMj+pEO9BMUz0xYNnrOgc2DACydCNfFcgYNZZWYxzs63EoqMfItlThHQK8Pxkd5mrEeJQYMftfQ/U2nZnNWRJYZk41AosBsO8XEZkbWCVg9QPtsNocfZ2SSXxHVpvTRAPv+fBWfrU+UgW19nZO6O8khlR1T6qqx9q8o9AHeN8nU0IB+Jk+LeMp+Ul4hPqClRoLo66BY/2efZg5c/zm/vuX28l/fv8z+1bs2ZA4A0Dr0btC2/OXx02gKE3qEbzmmtViczDu1gjSHgq9HtSresyL+7ts0UB3feUtns/CLp4WHAPRLMduxj4avtA23Fe+60hYzPFbblTGLZs3OiNAxl1ZDEk5kBgxWeAF51siuAcFoh4s5QtEMDSBaOKIzxUIHN6EYeD6yMHFf93jt1UtHtBonC0eVAZOkg7BzaNdVsKhy4qjRlaat1UtKzBKJ7mV/AqtS6usCB/T8WXFG7isOIESWQG3VSwrtgtk5TbKpiSh5Dy/urWv3lhAdkomWhMZwOQLqkaob/qmfGJB2eX2QLLwFA6yy4JAFmeQq1Iyu/EBHKexxpwDEp/HDjsIqx4V7tqi/1LwavSv8a91w92q1Ka21k6vaw0N5y/ola4158Cg37WGhmcj18nrW2sX6V5r6GFu5Po1rrXd31rzI7AwQgcWWd43a0+qOpVZSaW3DM3TR3YzzcHdv4UoAUOOd/xG3VEu7sJiWDGhLztv75WdiZhoKUv3OdEtKVRdY+kggOUA6iBasvA2sfWDaXib3avLjEvbUQJyayjQtnGvem3DtKf/rqMisHvAj6L3JMtVgdT3Z5LHBQTFM9+zaNlirjswsnbzXMSzbqzaPwiYXO7u3gxtdGZzXZOpfoqSsdOq9i1XNGDbT1qz4x+F2ZShdGRo+9mCcYOiVY9P5Wj0nxsbW46DwiAIXYuFNNmhvYtvwvo/Qhv9qZnVGIf7v8Y6nlndsD+Nl6vJqw40bJM6ygDO15FAtOBjaAV6MHD1mSzTIyxi9Rwti4vTdE0d9vfV9W3qBX3C1kM1/CYxs6A/3y+5CDlkzGjNnvTpc+HktAaGIL8kjIG/Iw9ktc6i16BDnm4dQnClH8mE6oOpBZCHG9Ro+eE+4RFMWqyyG7v3z2BFlykN4CvIINPW+KFJmIT0jq7qbRZHJilRFl3t9QEO3LHptplDSmlQHVF5AMYA1YdomkFd3cs3nX9Nv3caUhE9VeCGXn4F1Hhzy+JL0r/Z4eROsAr7f7VXGx7aAbvwR/WNDleHbx5VNJpd/EHy7d0szy4fVzejf+/uVTx4qT1o3ulEaWtl444oG3c6j+4dOENrBnrwfvTYaki7aNznunljFBy/cUehnkYwHPVSEg/Leu6TWRZPTe1HNyTatZpxB0F+paz0A8GYzrt4NclMycch3RgPd2ZCU6+Nz9Lpmg+t0eZTtfm6GV4XLeRSVx7vwhPfwl06AvvlanSlHiPSaJgb/Wm9oIT1YyH7BlsJbLX7wh6MdBhfWBZV7b4wQjCzfquyhbkiszmn35QBeEzF8pBAF33EyDcyMR5Th8cOrZzKVQUwjFGaYwWuBoyHR8FKhTdJkt6lydScKsiCq51IIUikHgw9lgN1ADyKw47jxQJmThhUR0SeXKirt1Gx/mV+zCZwQXnyPwZnGZw55Wo9O7ccizv5e01W5lihA5LcPFZAon06lR0r+FCvj1eeXK42V6oxHvrsQ5/3LsrzNeeI3yjzqcrcLBoTRVtdYp0PPeDiUMHoMFSI8ehwcCguudVkg64Mutp94BC6S/eLYmmMFyyDq3Y3OIC86i7NEpJTa2hsr7Tt9fyh2d4AKvJjNCtilE/phJhWy1zlGJEVhvkaVFuomxTdm5CHFLTaTXAAczWqpsoGWQlktRthZEHuPEmX9AfweDOr35uTpJgEO6RiTLaCzg3edX8s/nvMmra3ALBEGzWxPDrrBiEW4C9BrgL+NZRdXgSrm1ZO107D8J/bJqA5+6yakN6SHr67EXth+u3bKlbSFqYC6Fj3sDwjUTLbVGK0FJfSPS2eFE3Ci2e3e0EHVIwKwH6vA8T6r9T13uWovarcSg9SsU+pqS3tAOtmbSmvHWq/8WsPA6w/U9E2hpujDuNh2x4n5kU1+F08W1NlM2nxarS5ajauT5uhvftA1puxJkahoXaMR6ERgjPjTSuuiuaVhEnD3GBJ/wpmC/xGf3+63aNNoLMDdt2sL3Ww4CbNvG8Fugw5lymAOKQZY9qjYSDM5IJ0hq/2OCdCDkDw9fdFZZ0Z2N9/sJse7MrQhyFnwjAUQ47keqmi1yApEri7tiDuyHO7Bn7z1lObViDciKMils10sPU9eAdrA62200XV6MR0+T2ry6+4ZFoD25IG2Z726zwt3IuhoOuKohsMq9cmwpBNCjaZunRb4yNRzF01HZ1OtjWo2SLJK88M1VqOakkNp1ErZ/7Q9hZ4SPr6/RwZpDWyV0mkTVS5C1h90TyQvmA9HqjoY+ceV8t1hIWJIJtspJ0UhA1SwDJ5DjmgYTNh5/Q3+L20ZoSZosepbhFgfXncrHaa1CVabC5gXVLbN6ODMtYuOY6og9jbWD/cRBixlgInD/bDXtutFI8AQ5xxykBu5CdFHtjXJLYeNsduQGIBsGy28RMXC7Q/cdtuubFyIYGJMWcLCZWEk2REcCMRkBhRE6RRYs5NK22VmOaNlUuMQArpadvKr9DetEqMJL1hE4sHLDFWqEhiwI1VSwyGEkMp7Mrk3HWRzxH6TbnhTePptxctwqZzWtt5Px5f4ThiMwjrPXvSWWKQlURWfyYH2wpqyL5fRGRucJXBVX+9mg0rV27TKZnEd2Q1MTXEkvjq76KGbGhpb6NsShLKPVqy7I5NCWRjbt6UTywobtugaEGEDuJWQFPEQVfl8ndDcRBmoYxjHMfnrbsyhmNDU/hLIbToX69guQGl5Iw3cHpdbgfap1/Qa11uxOl83O9yezB0aFpbd+ezIbvR6WsnA/qaXSNujZyh9ly9GJHTximBMy2vuwNYv+/mQQpoul5L46rfd+N0zjWNr+WBHYDTxumRa3pfq4Bae/fr6jC76Scmr9Jx4ZSS9uwnYrjc6NUuN6e9Qs/LDcfGgnWWTzFpz5msPzqW9P/nerE8mLXbW8accNJrb4fPYXPSsctKd089fMZW8xwb3Er1cbMDkz31JeEfmT5+VFIlBFG8dnAo9RxWU/y8XmZeOy4QlAEUhLWkAW9iUAfzgDc7bKeJwI6nREYEhMDtO7PJgQGw4+0K6E3JclWg1dIoDzCLDvhA2CyfdXlsl2c2HHV84HjV92svwtv8Pvo3441Xu24B1k2Anatax4AbywqvjnUNKB5Un3wlnSPJzLKAVei8+upMq9CcbeOiXqwCrA9/bWJ6TCU5MtwLF8Fq+hgAsQqaZsY/N8U/wPjGxpbjoDAIKINupFl6LO+yxXzJV786VkunBfCOfjotOIMsuB9UmZUrvit3ztXlTD1nft9nsoSHDjuOxNphT9P113n8vrq+PYSlT9h6iBSymoEVn9e3sl8m5R6vNTe6Q5cIj1Z3YJTyS8K8jHfkgax47eSHr0lhM/YzAEXijFExHftry4MFVWPXsd/2bJjUoLBDv9tkL2czNmSxbbVZ8ttFk/4zwl7Nb4P7oGUB3H2AIpw3AyApLFBXRtlpLA5ik81qUoc5UtcMN3e4lcDohmkOUS1OIGqNu28YIAdrqIFqXQbSQ+sAh/lprRExhYgd7NioGa8TTmpV1v4fYRjSf0qXWZSYorUDqjGizFZmSOppVHNStD8x6iytzkHzeGkA2mzDdJNqsN7TMt6M9TD5zFwVGZFa+xBlM2NeXemJEwrqtbpRt8iHLa7MnPkDWjEmTYZ820ya7wxf/ZUnPmTXZtZ8B8jqrz1xYU3RfTLLKMUy9LqboxLQwlr75MtqzGrdCserSWZo9UH1GJExDqBKm9Fqneq03zz+HMBotYBXRGhGq/E1Y0TazJw2M1pNBb76qbULgyCPZBLnZuq4CvJlcxrc9B0DcWEMxLTfOKAUI9qoXRgDKUJbt1lsum/I4zuAjZpzwmgIliyuA4iAwLY5D9GUcwYhWOB0ZtaIaDEpN7uk1li7/tIqNQRvbkOXa1uh5PsOu8BKlGx2YVejtHlUFSlxKp6KF3RYuHRCOauawiU4BwT4eSzz4fSExObACa+ZCdtV1Qj4JNtrqRqB72iZj6LpHa2/owlX4zMUpVl60EPb9HUx0RZF0RZ3AI3PPZhtXrC9CnhD93gaMiI672EA8PZI86NpuSaLrn4y78GoiyHz0rjqJ/MeJ7ay0drCapHZnJMAbBAeV0+9AKrup9RES1UQLW5VX79H1QFU6M9U6M1GzdOI8dArHBxpPG5KNbrS6OtmDwwrDG7C2j+CBlvZsTUOOJll00oS0v+7BD2vC7MjqPQ7BRqT0sNQ6xbsiEQG6e6Q1u9fcbb3gqS9i2frVX7gPMxs79KELRDtg6yQsMEN/QNZbyp2LkHDhTnb+LZv5MPt+y7NEpJT/TLaLK3NsGLHE/W/VFbswGzSx2hWbOBP6YSYyXJ8DRmTVsPEUaozOcmjezOWQA7cAfAweDZZFdIabGWw1R/r9uER5JvJ32uyMnU7XVhj0OVC+NhZHbn2MYDcJIO3qcd4bDFGEN/f4mxlvOVOgqE2akZD3fCcaKi60YyY42LdT7cicBFc7KwAWaU1Y9J03immKQKQg1U738YIHlfepjPTg0oWWe1su+o2WUP2/SIic4OrDK7680nox3FUdkom8R1ZTUx8SxZg7ZMZMWtecqCUY1ercXhgDWecnPoe7F/naUG/m8PEpAaC7GpAvCC4qtWAVM8eqv/ottgDs/mNrcUelX4OpLco5kyeNAkrnfloYIKJcDdChTkqnCAqc8pM2kKrnozIK+OMOTVdZLsBV79v5sMpkK/Uyp849qvGCmxUFYJuWMGNtbvQFzNw9DEDfmHhNW7m2WDUMDaKJ1baltS8xdci2BJS5YoOba5GTWieitjM3HX2q1/V1LLa1vFJbhciZ52ORjxB9JhVVb6hIezsS5fNRvj1tKFhVrMgOovjNYmXjCwJu83MjA7FbcbQiarS/IEoGMdZmF6zZ4HfjERPM9mYKAWOMzwNqRd3XIJDdZbrXOnKiFznSmTNgWZ3sOp3mjGMdr5JkvQuTaamrZk8wPrPNTEMeT2YDheyuA7gXBND4/uUx4vFReQRKURW/4EmZ7rdbVRAUGaBbpoQ5ZTTG6jloHa1s6oQAwgv9ez6oJPU7jUHuiMwpwb/moVgbDM/1PruGgSo99+gJlqIw+NBnEuJFu6OTyzLu6odn9ALvn/V7/GJuKwHA4sQhcfzdExI8MCW5YkC3v3JhiTggQFcKeBeOCjAbes4mzGAH0hcEG2MXInGYAB3DEHoCXp3GMfW12GDiQYtfZ7hG5xT33DyJ7S9AZZ+7n8nRYfvyBCgc3TEE2a83rAIkI0MAVJ7CD40wLGxh5LQW4LQ20Nzdtg3N4NWlZV3W41qbrth9kWHNKrrpmRjWGx2P93JwUWcpp6VEuGeHL3XnxLhwpSI++lnsryMrqbqkNWeFWFzTuDMAOWO0NWeEmGj48n2hpYfINu+MC13h8XNHE7XhrnhZR3xMqfZdmcAJZ2cpoempLO96s8RBn8wJMyBprrqgPi0jKfGZMujrJ+Q2QggaAIrJxhvGwsbb3dYxtu2jx8qGug7hH5gMTWPP2XAkDZ50la1Hq96kXuCplxd9Ax7vOgZRfwi8lzPYmze+MYM2JxOa5SbV4NVL4Keq8NXP1fj9Eg0I92kcdUeNqviP2bmj2LL7O5b5gBzao38PsMpNqeb7dYwX8RmfZ5l7mRUCA9mhRoOZ8GY2U5dQMszyv1Cy75BvfM8/Z3pduM2cXAVLlUVaWt1qVg9kIIWDbwz6u3hx2Uw7fOyEbAw+kNxq3AANfzi3KqewNbuY2GX08iSrrIx01K46vexXOg7mwFAneE7gK4NLgx+PZJJnJuodhcUrC1F1A69veddQXGwlHnWFi8YupUIE/VuVaLx0DPb4p1t7HqlXQQ9U4evdkZmWzB2Qh2tLI7yjGqzgVcKXu3EzEa8hLJyn36IpplBWA7hIVAzuEObDofSuOpvp+XCc6t3dGGLvdnkBsoDrL+JlgtNrwmGyAPLAooagYVGF2AqmAtYwHBG4l9rUp9IZuCqyu0rEIt/kPx/5TPF39tGUm75aNdFqnjAmkhNo9VzldJ4KuTtGYKM3LRX3VqdJ4eWb4UtGq7qnvs1bpyQbH8U6F/fNmYBN+9zoA/+yW0x4NlPQ/xV9GfzoH7cpVlC8jQzJ3ry4STQc91niqLxQC/kOSIM9YvgMuelY4TC6A8lZFSVUdVjxdGsoKxP6YSY0aWSAGuPGWEfHs7T3TEneXRvevvKgas9YoR9DMCtCtMMtjLYDiBW5MBY0V2U52uOBTa8S5p3OaIFxQpn3YS8WTdbzC9iqz6voNgTxn4wrCvknciag7qO8NVPukIYDq45UAZeKXj10y6HH+03sMrAOgTGBYP8n9aLOEsvyAYrBFj/MZ3DCWwtitUx3pIctPoP6HyYrfxm8vearEwDpg7cpevmKGnXCvazIAWdJ3VtMS0Yyaycp4tgXGd5T5XajMd7si1evVGtAapBuzu09ftSvilXELbcp+Or3ZmqWgfxm1qbwoXeChc8TzQCqrC3NS/DuUyBNdt6qwqNyIhjXo6BMeJK0NZuxG0bknNjxDvDV7sRr4ak7LV+KMvCjf/dgfEGjR+cpjUXtN3KTi9txHPAd80BLkHFz0sbG99YChvxXPBL4mnqwNVurLEHwS2Oty5LldUBPABrjQHA23Ouj4VdM+jKoDuAY0zPNG5RAaz+40sPhkK3elvwUTKbE7Mzy0Gs/RjTRhhAeNLcoCibXI20/fzmZ5TOnHXMbRIYI1RiNr5JBBg6UZ/Jkpgxj5160+4IpjweGvx3CVv8eXHREfrRGDLxS8FYHazaPWgbQwb+JWGx7nfkgaxMNqEkyAq9aPowS9O8XkidRcvnh3QaF6/4fw==
\ No newline at end of file
diff --git a/compitino/secondo_compitino/schema_concettuale.pdf b/compitino/secondo_compitino/schema_concettuale.pdf
index 9ddd060..2bc4c58 100644
Binary files a/compitino/secondo_compitino/schema_concettuale.pdf and b/compitino/secondo_compitino/schema_concettuale.pdf differ
diff --git a/compitino/secondo_compitino/schema_concettuale.tex b/compitino/secondo_compitino/schema_concettuale.tex
index 56f28b7..699468a 100644
--- a/compitino/secondo_compitino/schema_concettuale.tex
+++ b/compitino/secondo_compitino/schema_concettuale.tex
@@ -1,3 +1,100 @@
% !TEX root = ../main.tex
-Vincoli non catturati graficamente: \textellipsis
\ No newline at end of file
+\paragraph{Elenco degli ingredienti disponibili}
+*l* committente ha chiesto espressamente l'elenco degli ingredienti disponibili.
+Tuttavia, questo è calcolabile a partire dagli acquisti e dalle produzioni.
+Ho convinto *l* committente a non memorizzare separatamente l'inventario degli
+ingredienti, rassicurandol* che avrei fornito una vista logica ``Inventario".
+
+\begin{lstlisting}[style=SQLu][float,floatplacement=H]
+CREATE VIEW IngredientiAcquistatiTotali (IdIngrediente, Ingrediente,
+ Totale)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(a.Quantità) Totale
+ FROM Acquisti a
+ JOIN Ingredienti i ON i.IdIngrediente = a.IdIngrediente
+ GROUP BY i.IdIngrediente, i.Descrizione;
+
+CREATE VIEW IngredientiInUso (IdIngrediente, Ingrediente, InUso)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) InUso
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato IS NULL
+ GROUP BY i.IdIngrediente, i.Descrizione;
+
+CREATE VIEW IngredientiUsati (IdIngrediente, Ingrediente,
+ Usati)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) Usati
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato = 0
+ GROUP BY i.IdIngrediente, i.Descrizione;
+
+CREATE VIEW Inventario (IdIngrediente, Ingrediente, QuantitàTotale,
+ QuantitàDisponibile)
+AS SELECT iat.IdIngrediente IdIngrediente,
+ iat.Ingrediente Ingrediente,
+ (iat.Totale - COALESCE(iu.Usati, 0)) QuantitàTotale,
+ (iat.Totale - COALESCE(iu.Usati, 0)
+ - COALESCE(iiu.InUso, 0)) QuantitàDisponibile
+ FROM IngredientiAcquistatiTotali iat
+ LEFT JOIN IngredientiUsati iu
+ ON iu.idIngrediente = iat.IdIngrediente
+ LEFT JOIN IngredientiInUso iiu
+ ON iiu.idIngrediente = iat.IdIngrediente
+ WHERE iat.Totale - COALESCE(iu.Usati, 0) > 0;
+\end{lstlisting}
+
+Ogni volta che si inizia una produzione, l'applicazione controlla che la
+quantità di ingredienti disponibili superi la quantità degli ingredienti
+necessari alla preparazione.
+
+L'applicazione può anche mostrare una ``lista della spesa" basandosi su ricette
+che si vogliono preparare e sulla vista inventario.
+
+L'applicazione mostrerà ad ogni birrai* solo le ricette di cui è aut*r* o di un
+birrificio per cui lavora.
+
+\begin{minipage}{\linewidth}
+ \paragraph{Vincoli intra-relazionali}
+ \begin{itemize}
+ \itemsep0em
+ \item Non possono esistere due persone con lo stesso codice fiscale.
+ \item Non possono esistere due birrai* con lo stesso soprannome.
+ \item Non possono esistere due fornitori con la stessa partita IVA né
+ con la stessa ragione sociale.
+ \item Il tipo di ingrediente determina l'unità di misura.
+ Esiste un breve elenco di tipi ingredienti disponibili con la relativa unità di
+ misura.
+ Non ho creato una classe ``TipiIngredienti" per contenere il numero di classi,
+ ma in effetti il tipo determina funzionalmente l'unità di misura ed esistono
+ pochi tipi, mentre ci sono molti ingredienti per ogni tipo.
+ \end{itemize}
+ \paragraph{Vincoli inter-relazionali}
+ \begin{itemize}
+ \itemsep0em
+ \item Alla registrazione, l'utente deve inserire un soprannome e/o un indirizzo
+ di spedizione: il vincolo di copertura impone che l'unione di Clienti e
+ Birraie sia Persone, non devono esistere persone che non sono né clienti
+ né birrai*.
+ \item In ogni produzione, il NumeroBottiglie diviso per 0.5 non deve superare la
+ CapacitàProduttiva del birrificio.
+ \item Ogni produzione deve iniziare con stato `in corso';
+ non può iniziare una produzione se un altra è `in corso' nello stesso
+ birrificio.
+ \item Ogni nota deve fare riferimento a una produzione.
+ \item Ogni prenotazione deve fare riferimento a una produzione.
+ \item Ogni prenotazione deve fare riferimento ad un* cliente.
+ \item Ogni produzione deve seguire una ricetta.
+ \item Due produzioni di uno stesso birrificio non devono avere lo stesso lotto.
+ \item Ogni ricetta deve avere un* creat*r* e un birrificio di riferimento.
+ \item Ogni fattura deve fare riferimento ad un birrificio e un fornitore.
+ \item Ogni acquisto deve riferirsi a una fattura e un ingrediente.
+ \item Ogni ricetta deve avere almeno un ingrediente per ciascuno dei
+ seguenti tipi: malto, luppolo, lievito.
+ \end{itemize}
+\end{minipage}
diff --git a/compitino/secondo_compitino/schema_logico.pdf b/compitino/secondo_compitino/schema_logico.pdf
index 8a0b33d..e21638c 100644
Binary files a/compitino/secondo_compitino/schema_logico.pdf and b/compitino/secondo_compitino/schema_logico.pdf differ
diff --git a/compitino/secondo_compitino/schema_logico.tex b/compitino/secondo_compitino/schema_logico.tex
index 2325a36..844e9cb 100644
--- a/compitino/secondo_compitino/schema_logico.tex
+++ b/compitino/secondo_compitino/schema_logico.tex
@@ -1,21 +1,63 @@
% !TEX root = ../main.tex
-
+\\
\textbf{Schema logico relazionale in formato testuale}
+
\begin{lstlisting}[style=SQLu,escapechar=@]
-Tabella(@\underline{ChiavePrimaria}@, B, C, D)
-AltraTabella(@\underline{ChiavePrimariaEdEsterna*}@, E)
-@\textellipsis@
+Persone(@\underline{IdPersona}@, Nome, Cognome, Email, CodiceFiscale)
+Clienti(@\underline{IdPersona*}@, IndirizzoSpedizione)
+Birraie(@\underline{IdPersona*}@, Soprannome)
+Birrifici(@\underline{IdBirrificio}@, Nome, AnnoFondazione, Motto, Stemma,
+ CapacitàProduttiva)
+BirrificiBirraie(@\underline{IdBirrificio*, IdBirraia*}@)
+Fornitori(@\underline{IdFornitore}@, RagioneSociale, PartitaIva, Indirizzo)
+Fatture(@\underline{IdFattura}@, IdBirrificio*, IdFornitore*, Data,
+ NumeroFattura, Importo)
+TipiIngredienti(@\underline{IdTipo}@, Tipo, UnitàDiMisura)
+Ingredienti(@\underline{IdIngrediente}@, IdTipo*, Descrizione)
+Acquisti(@\underline{IdFattura*, IdIngrediente*}@, Quantità)
+Ricette(@\underline{IdRicetta}@, IdBirrificio*, IdCreatrice*, IdRicettaMadre*,
+ Nome, DataCreazione, Stato)
+IngredientiRicette(@\underline{IdRicetta*, IdIngrediente*}@, Quantità)
+Produzioni(@\underline{IdProduzione}@, IdRicetta*, DataProduzione, NumeroLotto,
+ Stato, NumeroBottiglie)
+Prenotazioni(@\underline{IdCliente*, IdProduzione*}@, Stato, Quantità)
+Note(@\underline{IdNota}@, IdProduzione*, Testo)
+NoteDegustazione(@\underline{IdNota*}@, Giudizio)
\end{lstlisting}
\paragraph{Dipendenze funzionali}
\begin{itemize}
-\item Per ogni tabella la chiave primaria (sottolineata) determina ciascuno degli attributi della tabella
-\item Altre eventuali dipendenze
+ \itemsep0em
+ \item Per ogni tabella la chiave primaria (sottolineata) determina ciascuno
+ degli attributi della tabella.
+ \begin{lstlisting}[style=SQLu,escapechar=@]
+ IdPersona @$\to$@ Nome, IdPersona @$\to$@ Cognome, IdPersona @$\to$@ Email,
+ IdPersona @$\to$@ CodiceFiscale, @$\textellipsis$@
+ \end{lstlisting}
+ \item Nella tabella \texttt{Persone}, \texttt{CodiceFiscale} è chiave
+ naturale e determina tutti gli altri attributi.
+ Ho ritenuto prudente aggiungere una chiave artificiale perché, se è vero
+ che due persone diverse non avranno mai lo stesso codice fiscale, è vero
+ anche che ci possono essere errori umani nell'inserimento di un CF e voglio
+ riservarmi la possibilità di correggere un CF senza minare l'affidabiltà
+ della base di dati.
+ \item Stesso discorso per la RagioneSociale e la PartitaIva nella tabella
+ \texttt{Fornitori}: ciascuno è chiave separatamente.
+ \item Nella tabella \texttt{Fatture}, la coppia di attributi \texttt{\{IdFornitore, NumeroFattura\}}
+ è chiave.
+ \item Nella tabella \texttt{Produzioni}, il NumeroLotto \underline{non} è chiave, in
+ quanto birrifici diversi possono avere lotti uguali, è solo all'interno del
+ birrificio che il lotto identifica univocamente la produzione.
\end{itemize}
-
Uno schema R, avente insieme di attributi T e insieme di dipendenze funzionali F, (\lstinline{R}) è
in forma normale di Boyce-Codd (BCNF) se ogni dipendenza funzionale della chiusura di F o è
banale o ha come determinante una superchiave di T.
Esiste un teorema che semplifica il calcolo, asserendo che se la condizione di cui sopra vale per
una qualsiasi copertura di F allora vale per l’intera chiusura di F.
+
+Nella copertura di F che ho descritto sopra (che peraltro è canonica: ogni dipendenza ha un
+solo attributo come determinato, nessuna dipendenza è ridondante e non sono presenti
+attributi estranei, in quanto ogni determinante è chiave), ogni dipendenza funzionale ha
+come determinante o la chiave primaria o una chiave naturale che non è stata scelta come
+primaria, in ogni caso una superchiave. \underline{La BCNF è pertanto rispettata}.
diff --git a/compitino/secondo_compitino/source_code.tex b/compitino/secondo_compitino/source_code.tex
new file mode 100644
index 0000000..c5be7d9
--- /dev/null
+++ b/compitino/secondo_compitino/source_code.tex
@@ -0,0 +1,5 @@
+% !TEX root = ../main.tex
+
+\begin{center}
+ Codice sorgente e test: \href{https://gogs.davte.it/Davte/basi_di_dati}{https://gogs.davte.it/Davte/basi\_di\_dati}
+\end{center}
diff --git a/compitino/secondo_compitino/test/data.sql b/compitino/secondo_compitino/test/data.sql
new file mode 100644
index 0000000..6bfa138
--- /dev/null
+++ b/compitino/secondo_compitino/test/data.sql
@@ -0,0 +1,37 @@
+BEGIN TRANSACTION;
+INSERT INTO "Fornitori" ("IdFornitore","RagioneSociale","PartitaIva","Indirizzo") VALUES (1,'Luppoli per tutti i gusti',121457,'Corso Torre 125'),
+ (2,'A tutto Malto',147963,'Piazza Dante 16'),
+ (3,'Lievitami',236541,'Corso Pavia 33');
+INSERT INTO "Fatture" ("IdFattura","IdBirrificio","IdFornitore","Data","NumeroFattura","Importo") VALUES (1,1,1,'2020-01-03',125,77),
+ (2,1,2,'2020-03-12',116,40),
+ (3,1,3,'2020-03-18',78,82),
+ (4,1,3,'2020-04-02',96,60);
+INSERT INTO "Birrifici" ("IdBirrificio","Nome","AnnoFondazione","Motto","Stemma","CapacitàProduttiva") VALUES (1,'Pirati Rossi',2020,'Arrrr','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',0);
+INSERT INTO "BirrificiBirraie" ("IdBirrificio","IdBirraia") VALUES (3,1),
+ (4,1);
+INSERT INTO "Birraie" ("IdPersona","Soprannome") VALUES (3,'MaVe'),
+ (4,'GiuLe');
+INSERT INTO "Clienti" ("IdPersona","IndirizzoSpedizione") VALUES (1,'Via Ramazzini 14'),
+ (2,'Corso Milano 2');
+INSERT INTO "Persone" ("IdPersona","Nome","Cognome","Email","CodiceFiscale") VALUES (1,'Antonio','Rossi','a.r@g.i','NNNNRRRR'),
+ (2,'Enrico','Bianchi','e.b@g.c','EEEBBB'),
+ (3,'Giovanni','Verdi','m.v@l.i','MV'),
+ (4,'Giulia','Lelli','g.l@e.c','GL');
+INSERT INTO "Acquisti" ("IdFattura","IdIngrediente","Quantità") VALUES (1,1,12),
+ (2,2,7);
+INSERT INTO "TipiIngredienti" ("IdTipo","Tipo","UnitàDiMisura") VALUES (1,'Luppolo','g / L (mash)'),
+ (2,'Malto','g%'),
+ (3,'Lievito','g%'),
+ (4,'Zuccheri','g%'),
+ (5,'Additivi','mg%');
+INSERT INTO "Ingredienti" ("IdIngrediente","IdTipo","Descrizione") VALUES (1,1,'Luppolo verde'),
+ (2,1,'Amarillo');
+INSERT INTO "IngredientiRicette" ("IdRicetta","IdIngrediente","Quantità") VALUES (1,1,4);
+INSERT INTO "Ricette" ("IdRicetta","IdBirrificio","IdCreatrice","IdRicettaMadre","Nome","DataCreazione","Stato") VALUES (1,1,3,'','Bionda decisa','2020-01-01','');
+INSERT INTO "NoteDegustazione" ("IdNota","Giudizio") VALUES (1,7);
+INSERT INTO "Note" ("IdNota","IdProduzione","Testo") VALUES (1,1,'Troppo freddo ad aprile-maggio, meglio farla d''estate');
+INSERT INTO "Produzioni" ("IdProduzione","IdRicetta","DataProduzione","NumeroLotto","Stato","NumeroBottiglie") VALUES (1,1,'2020-05-01',12447,NULL,12),
+ (2,1,'2020-04-15',12443,0,0);
+INSERT INTO "Prenotazioni" ("IdCliente","IdProduzione","Stato","Quantità") VALUES (1,1,'',4),
+ (1,2,NULL,6);
+COMMIT;
diff --git a/compitino/secondo_compitino/test/data_and_schema.sql b/compitino/secondo_compitino/test/data_and_schema.sql
new file mode 100644
index 0000000..753ab3d
--- /dev/null
+++ b/compitino/secondo_compitino/test/data_and_schema.sql
@@ -0,0 +1,228 @@
+BEGIN TRANSACTION;
+CREATE TABLE IF NOT EXISTS "Acquisti" (
+ "IdFattura" INTEGER NOT NULL,
+ "IdIngrediente" INTEGER NOT NULL,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdFattura","IdIngrediente")
+);
+CREATE TABLE IF NOT EXISTS "Birraie" (
+ "IdPersona" INTEGER NOT NULL,
+ "Soprannome" TEXT NOT NULL UNIQUE,
+ PRIMARY KEY("IdPersona")
+);
+CREATE TABLE IF NOT EXISTS "Birrifici" (
+ "IdBirrificio" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Nome" TEXT,
+ "AnnoFondazione" INTEGER,
+ "Motto" TEXT,
+ "Stemma" BLOB,
+ "CapacitàProduttiva" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "BirrificiBirraie" (
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdBirraia" INTEGER NOT NULL,
+ PRIMARY KEY("IdBirrificio","IdBirraia")
+);
+CREATE TABLE IF NOT EXISTS "Clienti" (
+ "IdPersona" INTEGER NOT NULL,
+ "IndirizzoSpedizione" TEXT NOT NULL,
+ PRIMARY KEY("IdPersona")
+);
+CREATE TABLE IF NOT EXISTS "Fatture" (
+ "IdFattura" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdFornitore" INTEGER NOT NULL,
+ "Data" TEXT NOT NULL,
+ "NumeroFattura" INTEGER NOT NULL UNIQUE,
+ "Importo" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Fornitori" (
+ "IdFornitore" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "RagioneSociale" TEXT NOT NULL UNIQUE,
+ "PartitaIva" INTEGER NOT NULL UNIQUE,
+ "Indirizzo" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Ingredienti" (
+ "IdIngrediente" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdTipo" INTEGER NOT NULL,
+ "Descrizione" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "IngredientiRicette" (
+ "IdRicetta" INTEGER NOT NULL,
+ "IdIngrediente" INTEGER NOT NULL,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdRicetta","IdIngrediente")
+);
+CREATE TABLE IF NOT EXISTS "Note" (
+ "IdNota" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdProduzione" INTEGER NOT NULL,
+ "Testo" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "NoteDegustazione" (
+ "IdNota" INTEGER NOT NULL,
+ "Giudizio" INTEGER NOT NULL,
+ PRIMARY KEY("IdNota")
+);
+CREATE TABLE IF NOT EXISTS "Persone" (
+ "IdPersona" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Nome" TEXT NOT NULL,
+ "Cognome" TEXT NOT NULL,
+ "Email" TEXT NOT NULL,
+ "CodiceFiscale" TEXT NOT NULL UNIQUE
+);
+CREATE TABLE IF NOT EXISTS "Prenotazioni" (
+ "IdCliente" INTEGER NOT NULL,
+ "IdProduzione" INTEGER NOT NULL,
+ "Stato" INTEGER,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdProduzione","IdCliente")
+);
+CREATE TABLE IF NOT EXISTS "Produzioni" (
+ "IdProduzione" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdRicetta" INTEGER NOT NULL,
+ "DataProduzione" TEXT NOT NULL,
+ "NumeroLotto" INTEGER NOT NULL,
+ "Stato" INTEGER,
+ "NumeroBottiglie" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Ricette" (
+ "IdRicetta" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdCreatrice" INTEGER NOT NULL,
+ "IdRicettaMadre" INTEGER,
+ "Nome" TEXT NOT NULL,
+ "DataCreazione" TEXT NOT NULL,
+ "Stato" INTEGER
+);
+CREATE TABLE IF NOT EXISTS "TipiIngredienti" (
+ "IdTipo" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Tipo" TEXT NOT NULL,
+ "UnitàDiMisura" TEXT NOT NULL
+);
+INSERT INTO "Fornitori" ("IdFornitore","RagioneSociale","PartitaIva","Indirizzo") VALUES (1,'Luppoli per tutti i gusti',121457,'Corso Torre 125'),
+ (2,'A tutto Malto',147963,'Piazza Dante 16'),
+ (3,'Lievitami',236541,'Corso Pavia 33');
+INSERT INTO "Fatture" ("IdFattura","IdBirrificio","IdFornitore","Data","NumeroFattura","Importo") VALUES (1,1,1,'2020-01-03',125,77),
+ (2,1,2,'2020-03-12',116,40),
+ (3,1,3,'2020-03-18',78,82),
+ (4,1,3,'2020-04-02',96,60);
+INSERT INTO "Birrifici" ("IdBirrificio","Nome","AnnoFondazione","Motto","Stemma","CapacitàProduttiva") VALUES (1,'Pirati Rossi',2020,'Arrrr','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',0);
+INSERT INTO "BirrificiBirraie" ("IdBirrificio","IdBirraia") VALUES (3,1),
+ (4,1);
+INSERT INTO "Birraie" ("IdPersona","Soprannome") VALUES (3,'MaVe'),
+ (4,'GiuLe');
+INSERT INTO "Clienti" ("IdPersona","IndirizzoSpedizione") VALUES (1,'Via Ramazzini 14'),
+ (2,'Corso Milano 2');
+INSERT INTO "Persone" ("IdPersona","Nome","Cognome","Email","CodiceFiscale") VALUES (1,'Antonio','Rossi','a.r@g.i','NNNNRRRR'),
+ (2,'Enrico','Bianchi','e.b@g.c','EEEBBB'),
+ (3,'Giovanni','Verdi','m.v@l.i','MV'),
+ (4,'Giulia','Lelli','g.l@e.c','GL');
+INSERT INTO "Acquisti" ("IdFattura","IdIngrediente","Quantità") VALUES (1,1,12),
+ (2,2,7);
+INSERT INTO "TipiIngredienti" ("IdTipo","Tipo","UnitàDiMisura") VALUES (1,'Luppolo','g / L (mash)'),
+ (2,'Malto','g%'),
+ (3,'Lievito','g%'),
+ (4,'Zuccheri','g%'),
+ (5,'Additivi','mg%');
+INSERT INTO "Ingredienti" ("IdIngrediente","IdTipo","Descrizione") VALUES (1,1,'Luppolo verde'),
+ (2,1,'Amarillo');
+INSERT INTO "IngredientiRicette" ("IdRicetta","IdIngrediente","Quantità") VALUES (1,1,4);
+INSERT INTO "Ricette" ("IdRicetta","IdBirrificio","IdCreatrice","IdRicettaMadre","Nome","DataCreazione","Stato") VALUES (1,1,3,'','Bionda decisa','2020-01-01','');
+INSERT INTO "NoteDegustazione" ("IdNota","Giudizio") VALUES (1,7);
+INSERT INTO "Note" ("IdNota","IdProduzione","Testo") VALUES (1,1,'Troppo freddo ad aprile-maggio, meglio farla d''estate');
+INSERT INTO "Produzioni" ("IdProduzione","IdRicetta","DataProduzione","NumeroLotto","Stato","NumeroBottiglie") VALUES (1,1,'2020-05-01',12447,NULL,12),
+ (2,1,'2020-04-15',12443,0,0);
+INSERT INTO "Prenotazioni" ("IdCliente","IdProduzione","Stato","Quantità") VALUES (1,1,'',4),
+ (1,2,NULL,6);
+
+CREATE VIEW Query_a
+AS SELECT r.IdRicetta, r.Nome
+ FROM Ricette r
+ JOIN Persone p ON p.IdPersona = r.IdCreatrice
+ WHERE p.Nome = 'Giovanni';
+CREATE VIEW Query_b
+AS SELECT fa.IdBirrificio,
+ COUNT(DISTINCT fa.IdFornitore) DiversiFornitori
+ FROM Fatture fa
+ WHERE fa.Data >= '2020-01-01'
+ GROUP BY fa.IdBirrificio
+ HAVING COUNT(DISTINCT fa.IdFornitore) >= 3
+ ORDER BY COUNT(DISTINCT fa.IdFornitore) DESC;
+CREATE VIEW Query_c
+AS SELECT fo.RagioneSociale, SUM(fa.Importo) ImportoTotale,
+ AVG(fa.Importo) ImportoMedio
+ FROM Fornitori fo
+ JOIN Fatture fa ON fa.IdFornitore = fo.IdFornitore
+ JOIN Birrifici b ON b.IdBirrificio = fa.IdBirrificio
+ WHERE b.Nome = 'Pirati Rossi'
+ GROUP BY fo.IdFornitore, fo.RagioneSociale
+ HAVING SUM(fa.Importo) > 10;
+CREATE VIEW Query_d
+AS SELECT b.Soprannome
+ FROM Birraie b
+ WHERE EXISTS (SELECT *
+ FROM Ricette r
+ WHERE r.IdCreatrice = b.IdPersona);
+CREATE VIEW Query_e
+AS SELECT DISTINCT p1.IdPersona, p1.Nome, p1.Cognome
+ FROM Persone p1
+ JOIN Prenotazioni pre1
+ ON pre1.IdCliente = p1.IdPersona
+ JOIN Produzioni pro1
+ ON pro1.IdProduzione = pre1.IdProduzione
+ JOIN Ricette r1
+ ON r1.IdRicetta = pro1.IdRicetta
+ WHERE NOT EXISTS (SELECT *
+ FROM Prenotazioni pre2
+ JOIN Produzioni pro2
+ ON pro2.IdProduzione = pre2.IdProduzione
+ JOIN Ricette r2 ON r2.IdRicetta = pro2.IdRicetta
+ WHERE pre2.IdCliente = pre1.IdCliente
+ AND r2.IdBirrificio <> r1.IdBirrificio);
+CREATE VIEW Query_f
+AS SELECT r1.IdBirrificio, pro1.NumeroLotto
+ FROM Produzioni pro1
+ JOIN Ricette r1 ON r1.IdRicetta = pro1.IdRicetta
+ WHERE pro1.NumeroLotto = (SELECT MAX(pro2.NumeroLotto)
+ FROM Produzioni pro2
+ JOIN Ricette r2
+ ON r2.IdRicetta = pro2.IdRicetta
+ WHERE r2.IdBirrificio = r1.IdBirrificio);
+CREATE VIEW IngredientiUsati (IdIngrediente, Ingrediente,
+ Usati)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) Usati
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato = 0
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW IngredientiInUso (IdIngrediente, Ingrediente, InUso)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) InUso
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato IS NULL
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW IngredientiAcquistatiTotali (IdIngrediente, Ingrediente,
+ Totale)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(a.Quantità) Totale
+ FROM Acquisti a
+ JOIN Ingredienti i ON i.IdIngrediente = a.IdIngrediente
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW Inventario (IdIngrediente, Ingrediente, QuantitàTotale,
+ QuantitàDisponibile)
+AS SELECT iat.IdIngrediente IdIngrediente,
+ iat.Ingrediente Ingrediente,
+ (iat.Totale - COALESCE(iu.Usati, 0)) QuantitàTotale,
+ (iat.Totale - COALESCE(iu.Usati, 0)
+ - COALESCE(iiu.InUso, 0)) QuantitàDisponibile
+ FROM IngredientiAcquistatiTotali iat
+ LEFT JOIN IngredientiUsati iu
+ ON iu.idIngrediente = iat.IdIngrediente
+ LEFT JOIN IngredientiInUso iiu
+ ON iiu.idIngrediente = iat.IdIngrediente
+ WHERE iat.Totale - COALESCE(iu.Usati, 0) > 0;
+COMMIT;
diff --git a/compitino/secondo_compitino/test/schema.sql b/compitino/secondo_compitino/test/schema.sql
new file mode 100644
index 0000000..e521a4f
--- /dev/null
+++ b/compitino/secondo_compitino/test/schema.sql
@@ -0,0 +1,192 @@
+BEGIN TRANSACTION;
+CREATE TABLE IF NOT EXISTS "Acquisti" (
+ "IdFattura" INTEGER NOT NULL,
+ "IdIngrediente" INTEGER NOT NULL,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdFattura","IdIngrediente")
+);
+CREATE TABLE IF NOT EXISTS "Birraie" (
+ "IdPersona" INTEGER NOT NULL,
+ "Soprannome" TEXT NOT NULL UNIQUE,
+ PRIMARY KEY("IdPersona")
+);
+CREATE TABLE IF NOT EXISTS "Birrifici" (
+ "IdBirrificio" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Nome" TEXT,
+ "AnnoFondazione" INTEGER,
+ "Motto" TEXT,
+ "Stemma" BLOB,
+ "CapacitàProduttiva" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "BirrificiBirraie" (
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdBirraia" INTEGER NOT NULL,
+ PRIMARY KEY("IdBirrificio","IdBirraia")
+);
+CREATE TABLE IF NOT EXISTS "Clienti" (
+ "IdPersona" INTEGER NOT NULL,
+ "IndirizzoSpedizione" TEXT NOT NULL,
+ PRIMARY KEY("IdPersona")
+);
+CREATE TABLE IF NOT EXISTS "Fatture" (
+ "IdFattura" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdFornitore" INTEGER NOT NULL,
+ "Data" TEXT NOT NULL,
+ "NumeroFattura" INTEGER NOT NULL UNIQUE,
+ "Importo" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Fornitori" (
+ "IdFornitore" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "RagioneSociale" TEXT NOT NULL UNIQUE,
+ "PartitaIva" INTEGER NOT NULL UNIQUE,
+ "Indirizzo" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Ingredienti" (
+ "IdIngrediente" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdTipo" INTEGER NOT NULL,
+ "Descrizione" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "IngredientiRicette" (
+ "IdRicetta" INTEGER NOT NULL,
+ "IdIngrediente" INTEGER NOT NULL,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdRicetta","IdIngrediente")
+);
+CREATE TABLE IF NOT EXISTS "Note" (
+ "IdNota" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdProduzione" INTEGER NOT NULL,
+ "Testo" TEXT NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "NoteDegustazione" (
+ "IdNota" INTEGER NOT NULL,
+ "Giudizio" INTEGER NOT NULL,
+ PRIMARY KEY("IdNota")
+);
+CREATE TABLE IF NOT EXISTS "Persone" (
+ "IdPersona" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Nome" TEXT NOT NULL,
+ "Cognome" TEXT NOT NULL,
+ "Email" TEXT NOT NULL,
+ "CodiceFiscale" TEXT NOT NULL UNIQUE
+);
+CREATE TABLE IF NOT EXISTS "Prenotazioni" (
+ "IdCliente" INTEGER NOT NULL,
+ "IdProduzione" INTEGER NOT NULL,
+ "Stato" INTEGER,
+ "Quantità" INTEGER NOT NULL,
+ PRIMARY KEY("IdProduzione","IdCliente")
+);
+CREATE TABLE IF NOT EXISTS "Produzioni" (
+ "IdProduzione" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdRicetta" INTEGER NOT NULL,
+ "DataProduzione" TEXT NOT NULL,
+ "NumeroLotto" INTEGER NOT NULL,
+ "Stato" INTEGER,
+ "NumeroBottiglie" INTEGER NOT NULL
+);
+CREATE TABLE IF NOT EXISTS "Ricette" (
+ "IdRicetta" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "IdBirrificio" INTEGER NOT NULL,
+ "IdCreatrice" INTEGER NOT NULL,
+ "IdRicettaMadre" INTEGER,
+ "Nome" TEXT NOT NULL,
+ "DataCreazione" TEXT NOT NULL,
+ "Stato" INTEGER
+);
+CREATE TABLE IF NOT EXISTS "TipiIngredienti" (
+ "IdTipo" INTEGER PRIMARY KEY AUTOINCREMENT,
+ "Tipo" TEXT NOT NULL,
+ "UnitàDiMisura" TEXT NOT NULL
+);
+CREATE VIEW Query_a
+AS SELECT r.IdRicetta, r.Nome
+ FROM Ricette r
+ JOIN Persone p ON p.IdPersona = r.IdCreatrice
+ WHERE p.Nome = 'Giovanni';
+CREATE VIEW Query_b
+AS SELECT fa.IdBirrificio,
+ COUNT(DISTINCT fa.IdFornitore) DiversiFornitori
+ FROM Fatture fa
+ WHERE fa.Data >= '2020-01-01'
+ GROUP BY fa.IdBirrificio
+ HAVING COUNT(DISTINCT fa.IdFornitore) >= 3
+ ORDER BY COUNT(DISTINCT fa.IdFornitore) DESC;
+CREATE VIEW Query_c
+AS SELECT fo.RagioneSociale, SUM(fa.Importo) ImportoTotale,
+ AVG(fa.Importo) ImportoMedio
+ FROM Fornitori fo
+ JOIN Fatture fa ON fa.IdFornitore = fo.IdFornitore
+ JOIN Birrifici b ON b.IdBirrificio = fa.IdBirrificio
+ WHERE b.Nome = 'Pirati Rossi'
+ GROUP BY fo.IdFornitore, fo.RagioneSociale
+ HAVING SUM(fa.Importo) > 10;
+CREATE VIEW Query_d
+AS SELECT b.Soprannome
+ FROM Birraie b
+ WHERE EXISTS (SELECT *
+ FROM Ricette r
+ WHERE r.IdCreatrice = b.IdPersona);
+CREATE VIEW Query_e
+AS SELECT DISTINCT p1.IdPersona, p1.Nome, p1.Cognome
+ FROM Persone p1
+ JOIN Prenotazioni pre1
+ ON pre1.IdCliente = p1.IdPersona
+ JOIN Produzioni pro1
+ ON pro1.IdProduzione = pre1.IdProduzione
+ JOIN Ricette r1
+ ON r1.IdRicetta = pro1.IdRicetta
+ WHERE NOT EXISTS (SELECT *
+ FROM Prenotazioni pre2
+ JOIN Produzioni pro2
+ ON pro2.IdProduzione = pre2.IdProduzione
+ JOIN Ricette r2 ON r2.IdRicetta = pro2.IdRicetta
+ WHERE pre2.IdCliente = pre1.IdCliente
+ AND r2.IdBirrificio <> r1.IdBirrificio);
+CREATE VIEW Query_f
+AS SELECT r1.IdBirrificio, pro1.NumeroLotto
+ FROM Produzioni pro1
+ JOIN Ricette r1 ON r1.IdRicetta = pro1.IdRicetta
+ WHERE pro1.NumeroLotto = (SELECT MAX(pro2.NumeroLotto)
+ FROM Produzioni pro2
+ JOIN Ricette r2
+ ON r2.IdRicetta = pro2.IdRicetta
+ WHERE r2.IdBirrificio = r1.IdBirrificio);
+CREATE VIEW IngredientiUsati (IdIngrediente, Ingrediente,
+ Usati)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) Usati
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato = 0
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW IngredientiInUso (IdIngrediente, Ingrediente, InUso)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(ir.Quantità) InUso
+ FROM IngredientiRicette ir
+ JOIN Ingredienti i ON i.IdIngrediente = ir.IdIngrediente
+ JOIN Produzioni p ON p.IdRicetta = ir.IdRicetta
+ WHERE p.Stato IS NULL
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW IngredientiAcquistatiTotali (IdIngrediente, Ingrediente,
+ Totale)
+AS SELECT i.IdIngrediente IdIngrediente, i.Descrizione Ingrediente,
+ SUM(a.Quantità) Totale
+ FROM Acquisti a
+ JOIN Ingredienti i ON i.IdIngrediente = a.IdIngrediente
+ GROUP BY i.IdIngrediente, i.Descrizione;
+CREATE VIEW Inventario (IdIngrediente, Ingrediente, QuantitàTotale,
+ QuantitàDisponibile)
+AS SELECT iat.IdIngrediente IdIngrediente,
+ iat.Ingrediente Ingrediente,
+ (iat.Totale - COALESCE(iu.Usati, 0)) QuantitàTotale,
+ (iat.Totale - COALESCE(iu.Usati, 0)
+ - COALESCE(iiu.InUso, 0)) QuantitàDisponibile
+ FROM IngredientiAcquistatiTotali iat
+ LEFT JOIN IngredientiUsati iu
+ ON iu.idIngrediente = iat.IdIngrediente
+ LEFT JOIN IngredientiInUso iiu
+ ON iiu.idIngrediente = iat.IdIngrediente
+ WHERE iat.Totale - COALESCE(iu.Usati, 0) > 0;
+COMMIT;
diff --git a/compitino/secondo_compitino/testo.tex b/compitino/secondo_compitino/testo.tex
index d1fbd69..f54f774 100644
--- a/compitino/secondo_compitino/testo.tex
+++ b/compitino/secondo_compitino/testo.tex
@@ -1,3 +1,88 @@
% !TEX root = ../main.tex
-Il testo viene assegnato dal Professore.
\ No newline at end of file
+\paragraph{Introduzione}
+La birra fatta in casa è un'attività che riceve crescente attenzione da parte degli appassionati.
+Ogni birraio amatoriale possiede un'attrezzatura per il processo di produzione della birra su
+piccola scala (bollitori, fermentatori, tubi, ecc.) con una certa capacità massima di
+fermentazione: il numero di litri che l'attrezzatura è in grado di gestire in un unico ``lotto". La
+preparazione della birra richiede anche ingredienti, le cui quantità effettive variano da una
+ricetta all'altra, questi sono vari tipi di malto, luppolo, lieviti e zuccheri (e, naturalmente, acqua).
+
+Ai birrai piace registrare le proprie ricette per riferimento futuro e mantenere un elenco
+aggiornato degli ingredienti disponibili per fare acquisti prima della successiva produzione.
+
+L'obiettivo di questo progetto è quello di sviluppare un'applicazione per i birrai domestici che
+consenta loro di mantenere un elenco di ricette e adattare quelle esistenti. L'applicazione deve
+anche:
+\begin{itemize}
+ \itemsep0em
+ \item mantenere un elenco di ingredienti disponibili;
+ \item aggiornare questo elenco dopo un ciclo di produzione e quando vengono acquistati nuovi ingredienti;
+ \item produrre liste della spesa per il lotto successivo;
+ \item guidare il birraio nel processo di produzione.
+\end{itemize}
+
+\paragraph{Descrizione del progetto}
+``Una cervecita fresca" è un'applicazione che consente ai produttori amatoriali di birra di
+mantenere un database organizzato delle loro ricette di birra. L'applicazione consente agli
+utenti di creare, archiviare e modificare ricette, e successivamente eliminarle, se l'utente
+desidera farlo. L'applicazione è destinata solo ai produttori di birra con metodo
+\href{https://www.birradegliamici.com/fare-la-birra/all-grain/}{all-grain}, e
+quindi tutte le ricette sono per questo tipo di birre (le birre ``estratto" non
+sono supportate).
+
+Ogni birrificio domestico dispone di un'attrezzatura specifica, le cui caratteristiche portano a
+una particolare ``dimensione del lotto": il numero massimo di litri che possono essere prodotti
+in una singola produzione.
+Le ricette prevedono, oltre all'acqua:
+
+\begin{itemize}
+ \itemsep0em
+ \item malti
+ \item luppolo
+ \item lieviti
+ \item zuccheri
+ \item additivi
+\end{itemize}
+
+Mentre i produttori di birra preferiscono creare ricette riferendosi a valori concreti, come
+chilogrammi di un particolare malto o grammi di un particolare luppolo, l'applicazione deve
+memorizzare queste ricette in una misura ``assoluta", che consente una conversione diretta
+della ricetta quando l'apparecchiatura, e di conseguenza la dimensione del lotto, è diversa.
+Ad esempio, una possibilità è esprimere la quantità di malto in percentuale del totale e usare
+i grammi per litro di miscuglio (mash) per il luppolo.
+
+Oltre alle ricette, l'applicazione deve conservare le \textbf{istanze} della ricetta, ovvero singole
+produzioni basate su una ricetta; queste istanze possono essere accompagnate da note per
+fare riferimento a problemi che possono influire sulla birra risultante, note che i produttori di
+birra vorrebbero rimanessero memorizzate. Un particolare tipo di nota sono le note di
+degustazione, che consentono ai birrai di tenere traccia delle opinioni su una birra di un dato
+lotto.
+
+Oltre a queste funzionalità più tradizionali, l'applicazione “Una cervecita fresca”, mantiene un
+elenco di ingredienti disponibili. Ciò consente ai birrai di avere la lista degli ingredienti
+mancanti per la prossima produzione. Un'istanza della ricetta, ovvero una produzione di birra,
+dovrebbe consentire agli utenti di aggiornare l'elenco degli ingredienti disponibili, sottraendo
+gli ingredienti usati da quelli disponibili.
+
+Sarà inoltre possibile per i birrai vendere la birra prodotta. L’applicazione deve offrire
+un’interfaccia web per la prenotazione e la vendita. Un cliente registrato può prenotare un lotto
+di birra in produzione, oppure parte di esso. Quando il lotto è stato prodotto, il birraio può
+confermare le prenotazioni e procedere con la vendita oppure, se non è soddisfatto del
+prodotto, cancellarle, per non danneggiare il proprio buon nome. La birra non prenotata può
+essere messa in vendita e comprata da utenti registrati.
+
+\paragraph{Scopo dell’applicazione}
+Il sistema deve implementare le funzionalità sopra descritte, ovvero creazione, modifica e
+cancellazione di ricette, creazione di istanze di ricette (birre), supporto per le note sulle birre,
+controllo degli ingredienti disponibili, supporto alla produzione con allarmi, supporto alla
+vendita.
+
+\paragraph{Scopo del progetto per quanto riguarda Basi di Dati}
+Si integrano i requisiti già specificati con le seguenti ulteriori informazioni:
+\begin{itemize}
+ \itemsep0em
+ \item le ricette sono relative ad un solo birrificio ma possono essere condivise tra
+diversi birrai che sono autorizzati al loro utilizzo;
+ \item gli ingredienti possono essere acquistati da più fornitori (registrati).
+\end{itemize}