From 4c4ffa048f74450abddf6e24b5c814a194ff0ac6 Mon Sep 17 00:00:00 2001 From: Davte Date: Sat, 30 May 2020 15:28:21 +0200 Subject: [PATCH] Second assignment. --- .gitignore | 3 + compitino/main.tex | 29 ++- compitino/secondo_compitino/dominio.tex | 74 +++++- .../secondo_compitino/piani_di_accesso.tex | 242 ++++++++++++++++-- compitino/secondo_compitino/queries.tex | 122 ++++++++- compitino/secondo_compitino/schema.drawio | 2 +- .../secondo_compitino/schema_concettuale.pdf | Bin 24238 -> 34111 bytes .../secondo_compitino/schema_concettuale.tex | 99 ++++++- compitino/secondo_compitino/schema_logico.pdf | Bin 20666 -> 23408 bytes compitino/secondo_compitino/schema_logico.tex | 56 +++- compitino/secondo_compitino/source_code.tex | 5 + compitino/secondo_compitino/test/data.sql | 37 +++ .../test/data_and_schema.sql | 228 +++++++++++++++++ compitino/secondo_compitino/test/schema.sql | 192 ++++++++++++++ compitino/secondo_compitino/testo.tex | 87 ++++++- 15 files changed, 1131 insertions(+), 45 deletions(-) create mode 100644 compitino/secondo_compitino/source_code.tex create mode 100644 compitino/secondo_compitino/test/data.sql create mode 100644 compitino/secondo_compitino/test/data_and_schema.sql create mode 100644 compitino/secondo_compitino/test/schema.sql 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 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/compitino/secondo_compitino/schema_concettuale.pdf b/compitino/secondo_compitino/schema_concettuale.pdf index 9ddd060602b579a26b2eb0a328dbbe57fa5cf168..2bc4c58a95c464fe98aa431a8ad12eba775158a4 100644 GIT binary patch delta 31467 zcmaHSV{j&2)NPW9Z9cJW+qUgwVka}v6HIKI6Wg|J+qRuM?|1Ky`|GRfTDy9$eY$FQ z)!Dty*{7>ILA%4jVs~g*xR}|PIGH(UnV2a5UDU9Q@(yNV#;)c>RAM|VOe{=H?Efz$ z0Ty%?lq(??lrZ5PR1L_?#>v4fAVB2e>TGUo2m34Y(r0~&jNAUmhhN+PFSTI`sz)oA zzn*n@3%3VphWE*2*3QUsn^4QQfJ!Az`};el99DlT%vw#8j8ug9RxU37idyl@1@2+{ z`s&Iu>rr4obN}hSI_GPeazoK+$jhd3TLs6JUAOD=kum4%kq~JAEv#7Z4tTJx+*o>z zNDt-wcozI}O^E3JdM^fksCIq6e;+1$O*O~;(0OlG{1*A<2i6pODH6UJb);w?U39+4 zp7jZSmF@)o9?-qIeL63mJ3PZ`J9|;G`Dot>D?)z7a1aFUl}}9X(2re>cb_2cNJ`Qh>S2a9XloWtGzT5W~`$M^jP=e0aq=}<7Tc&@jQB+KDK)1mf z2GgKKZ7LdX6UYmAa5!Lpn1ti>Po2Y7C%=!}ZB{TM!$+9~=j{$Ky#kCDf_PpoC-80H z#Vt?q1Ejw}Ctr(xu4Vc{hd?M9_Ylo*^(uXJvuGLe-HsD2+uRRCE3WP0`s&?%%>0@tS7(pNri{oyO$`C zIIF8G?NJhkboVA7vy8AEp8whgRv-1v_CX2XDs*yppupQ9g&2Y5A^ldie2mOpSjTpV zHnD>y&j7|71k)QG{&?OyO5I1xXx202Kxz|ku;-U(PFvd*PW>K836=Klsenn0%k3gk z*ZuQhSP&0Zj*V*2YP4IKa%0fv1#=z4(2=89Z%ABb%21y(I8*Om_28h;GOdX+1G`73 zWl%Gnb5h7bbl);^o$9eSFCkhSBCcoA=U~+JybeTmI{ko010jOvo7DY#J1}Qi=md{~ z)gh;}Lx_Y*p$mXVeTX5aPclMDfk`BYO-42`p_)^dK3K|(uJ9Z!_ax;4ASXup2gB%zipfX#2!0-p7l|awtac*mTtwwx$g?> zxB&MHSW`Ge^{_0e9(x=OZ3&~$56}dZBM%ChDc>^!B>@gyQN5%JUp5EIbD=PYAMB^- zy-Zt9F8Y+IQo(p;Hr}h?;^Bw^bFu@ph<4!P6}x}{n4-ILDPg5JS4oz)05-ZrLp6&N ziyvOo*h9cxEt}`T+MTOg@;UzqzXy7|%S7s(xho`>^?5|!`8TwN1;WooMuhA>= zcEOqp`+b2j)=~ZhX~?~h6^o4traiyeK}N7N*fi@!FGKkUu&#|Ay_<-u*mKk8(1;C2 zuPdx8t-KaOgSl$&MKC?6uJE*DjH61iEaRUCTIh}j7Z=`Riy8Lf(uW$lhewM@#lY=| zd7PnmSZp|Op}i2z{8SmlT#^#Mx=>JXZaa8XZg9DShJYGb6ImJWZYDJ|JSKZcA}bss zZ$$$QbKw>(0?OPu?Vc5Kb7UJr3Dbn?Qm^Cd;6bXYI4&$%{G139^Fa@~sYC1bui@Iv zJJSLuy64SZvgpGjytDkbQK)Fra$qtOfY}6CqRVtHQ8O&9Q`Ir7uVd#$S6nH;$3LgSmThk}%SsQaHDGab1nH$r+H#L(HAq;+ z8ja#nj6dGC%YC#J>c~=qa#S#ww-mNW5rEb$UqPOE-GY?@Z^+_3dIJQ-0dCntDlg(Z zu5n?+()1fuu>vAee@FXQ#ZNF#AY{Njy{baUs0>etSbIN?7pKoVBiyuG^ek%c7+w(U zlub-blXA~$oaG&jYDyW-?8xi`$zlAB9w1l-UdS35TL6~*hwA(Azb7S7O$82L_ z&c<}hs?#Vw`Y&hMU`CuSvzKl^cn6PwEWb!@D3WR(P`;)PRaEnbqBD7brX=NR_rR_w9b~-A)xTkwW>T4TB%eXS!=VV z4Z-Ko4AL;lqYP;#L+34z^5nU%BMPQQQe1ibR~{8ek_uiwrBO_He)4Mt6$rYa4H{~$ zq&R5mLoYQf2q6YU|1YJ;C|pGG-RmoEdK+_>o7>h&;CYp)E`{EA^8?_=rt^_f-QjGW zz3i3$0sVe7Ko^UvF0KefxwEK5oNv)F_I;Po8r?thD_5%dp zZ_@CP#&OKQszi`)6Uk8Z96JA{?&Eqo$0ViPP+*W^8rAEEA2+-gem818gQ55>73>lB zOL-t;&4IAs4=f8gdEOnU{u%+2?Q#M9FsXNc;9hpNa(0zdV`Oz45ZrbrA50tq0u?L` z>~(^1q%CR)%K=O3p^4y1hiI*lB3M{uq=D8HB;jY?^;l}o>!JDxnfD5%AoZ+B${2P_ zrG9a8gHc+7pFU;YTU8{eTz-%`7(Y$F81O+KC$QP=tNeNlyN65Xq@5{Ph?8M*2o>iR zDEui;5B+3UVbykTsvMD~*KD>`4cJ7I?V9pG)616(o8tCdIK4OsGs_xwJ@|Q_X1zNk z-g&jf;OlI6K|=k$Rz}QV?qf%dTFQZVY4PdME;KH&=1!fmBkefnKAW;zRXJA^wbw*D z@<%`fj=q+F^RG6ZoV0WTZ4yL@#z1Ew@WZ*OI@5ep>FYjAU4cKOkna*Dx8oY6P{ldl zbv!}T*GIU(-3ur`NZy)qU=aV_FH?mf+5@|6o^Os}F8X-bw5V$Ls75R3AZqtkaUN7E zFK1_>g{GbH%OMSdCsna94(naKnElRVe(xp@OEgB*#?1H=Cu?b>9d+qvTnf`9P}JrC zONaDYMr%KSE+F$gkNqzG#aM@wad0Me`L2}xW3m%uq%n^+C_0Av_}#wr&%fw>z=^@s zfl^%xKlef@AV*3g%;R7sy*Gh=hwO-dFwTovy$XibW7 zQ9>s^HFHfW#+sDAHv1oy4+4yz$CYl7;AxP!)9LRlxNvT&icHE*48AU7vGy!wn}aLd zoh=Y?CUK2O5cTm9&Zl_rTHY{>_maLMZxt*!;Bir0nZfpvH}#$cnBw{q4nb%NyT7NL z0}O2b+|{NC3i2g9tG>!kbFXxFbn6b{4heq0&I^9kZib!!zc_K}9Dwn{lWZiO)d`Mx z_Q0>ldBLDqR_-ZMz6uJQz&HHxua4O;~893EL%HAa}e7PiY z+{U5p#y~Q-@<3C!P$0VbEC1)`{&}={D3uS1fJY>lzr%8E>K*CX+nF{Rq@1d6APi1$ z_V+DL;rHvMy1?9W0J|ykqONUK_X!-h*!u)n{%5~Kz;|LpPPJ~8-uf0QW<+&SzhD9e z=_}lVoEZ4~dklwi48>SE#nv2#;l|ISaq}f5k+g{BwyDM^Z=l|xN8-L@#>>Y|!NQ-% zi|Xv0hnZ^i1bX&98464(?MJh+hy}M=Ff9)r%&*VUqFS`tP~P#%V()6739P#BNiq2Q zn^IpfbDi#ymTeb6D#>ftC$6qdav{CuH__et)&sc(Q0v!M0KW6*^*zDa&*|i!MXw0& zIe|3lp)}9s)xhpkS)Yu?O=I$5k0JUwqH+iMH?`zFti$iZuff>Sgz>)}O#9nSfd`xd zC$k-{miKL{02ItBbG$Pqv3r;M-$L8Vn5k`-)odIs_xreBU2`jzXy4RPm$1$$V{&%X zBDzU|+gdK7U@gv;ce0v?WYjZ*izVr_>*daKsU0*>-@vglfL>=ijisAq3i`Z5G*^E4 z36z|BV=ak!TW?;-g5)&_vCY%kST-o$pt@u+-*XYKh9m-&h%D_f6!@gOW-F!5xQ~U5uxsI<8;eR7^z7nT(z96Qy{X$b z<|hBN0@y#T(EC4H!DD$}Z_Z2ln!Ho60{B2c>!dQ9#5I0%zp|yvB|8Df`&Djm>iM%& zG6!DAcG0yQaJOPdtrg*Qr*J+3svDZBheOI?0>p(0>{yjyM~5>fDedn(lUzE-SL9->b9!b@2>ql z!DCwSGmE3>v7hycLo5{=yHC!D4``kB(~hL(!j6SL&3jtFFyAZeio8v*;>1^=h%e-- zk6M|vzXlhOoOzW60r%J++Q+c!Ftl zv$-aQI%61wru{wnF!C<&#u6>iY#Xg-Adh~vY*yOStv;Qv*?RU&ndq~fF?@jP&j#Y3j z4{w7j6MhqVSc#J?$us}g$r4XAwrKMXb2@^rpJ7dg9i@9^T+^W=P+o8Hk@-?heS6)l z>#Ct1VZK8zCbq6IoVbcE59o@`@x7KH!tbP5M^a!$xHa3l!AH6hF~stPHl)|i7!Bi* zgWujZ%RRL9%kiW8_K<84`CQBz%@3tfy20!gf8ICjg1jzeU9%A=xqbi6 z%hj4sr>NZj_`m@x49mk285!nDG&RjYy9eZ9wZ`|G|}raoXzv<@_p-38G}|G9@9 z-XjX9!|cZ!)haj;P37r`+{-@+Wg{ZPJX+EAsICheO(!Qxe{(0Y8Ub$TE0`V)Jw}sK zxnH`8bT)nv3434Gj4`fL>}eQPn{`ObWjuoYPs}Q|Y3X%%q_U^V)90Oihiwd+2jpAA z?faHB!p^3j%iu^YQRV@YjHOaFD~xRukpcp?d$d9AIyo_rsBlE_h({@pXY{jF3KbOd zPAI!5X6C>hF4|f1Xeh;j&h%4Y!m# zkOyAxoY|@HB*~5g5f^T0fS_;cJTtD1u0iiXvc?mC^SOAw6 zg5|rCSgto^<`UN3fen{{52IPemHH{ud!ZmpBzF#kr=`CsDuTI}NjfI{@dva#2Tjos zLe4D6xA>@+#tnHpW-M3YW9skFht2@cE=XbGt+Cv*IJ(HPP=QnY^rKru+%4P1LZT z75>(u-CB&WK*)uA|79s_zh)XHFrutgNyTi1k+>!vg@F9au|gh+HxSwZU3}aK@ROjP zi=GZL6dGoM+IQPAH|R`hTdBg}w$=nD2@%O3k^#=O%-xZhmjIV~-p33!QF;Wrx{HELxBxtXxHBuik!~wzNfpY89LUr6pr|yW<+J=lQ{}EY zxn;qSXCY`Eng+veo}~td`#C_@WaI|5Ye%N=*}}AWd!$}g!P51?*^u?i>vNUmu2^c% zQ}|>x#Ue!ZTU$B9FztrYKRKZ#sO-&sOdo^w8>h53Iw@cuQFWGXjjJI8g1Gm9S|gwo zJl6{P)|ZbK(4=5-FLBL>OuR-sX0QWsAj5XCmFJw2GyrIkGS^@EsB|gG<~eiO{-InJez zO8DoXC{tUjfNMp2tCWP{DUgT*HwQY>w7`<3*)b@4AQVi4s0Y?%=RnCCw~5MS32*KQ zIF^dIK+1oIH*L^JU;>P{T~x)jQpF4;+-Tr(HYptzlef>sSg^7=Vb;xyOzHGfu z9ONMJQ^FdKx_};Qxst=xCK#qWEV79;3HX^m{Cks2x9O}WI+hrqq>_vg?CS5MGZScL z>wPSdpXMvueQ;Hi4DapMUHY`^Glbjg4F2bV*@Uj%A*)~RDRmMPLdzv}7Ei_tjF-a{L6HCiSVgKVYod@s~KP1QEv>Z(4)*rh>!ZIakf$C&K6t^5sn*f7gml?@X9J{`c0KvcQPa+Tt?A{GyN=eP%jD>PhwkIl zSBI_Oz2Do3J!F=KVw$g5+SrD!ltEwCKjN#kr3mWDK2|G%b|$`PtH9ESi(*QhqA5s= zP7l2&f~JlD5v6_{7^2k%$hpNrFHTLz3zS^Q$2Y(~LDjmf5!q}GzS7p!q3=j&U`hUo z9Y?0f*8+j@3e+VhU#-zvRQ(||)H^Ll<}7dQH*GnZMDuCO9#E}(ONEbIjf3|$4g=fA z12YDaA=m028#4^yRlAcf7X-J6)Zp=??`=+LF$(_z_<$CRE*flXMiLtl2Uc*a`?%-h`7w|D_$&UyL zh0{@AHjJf)WHsh~pGr>j`_69O$f}A@vMM4pR};;U594C`h&tktj!$PA0*}hJ0I;9U zzU5pA#3dx)XUcAz!gXm^P9p+fGvzt0px%1+l!uxCkl2`N-5$yqsorI9I#`2#Q^(5s z>%ktV5INAsP9G6BKJyi5W2Sx-xDA}$vMp1PfXM3U!P}BoAed=Q!H#=!cyyQ>>>1|k zefAYML^LNx0J7rhMGlsEjtJ`S9NrZV_NtD6_ZxWD$?C#mL|gA*MB06@sfmt9bxm4@ z4xluH*?wa~7=EKPnR*S;=uD*qg+%7pfx^Ak-(r#^iCubTW+0l2p^5I7C}SI(}`Ce63Zd_Iin$dd)ToJmu8L$5%2o zrPV$DzCUMfn_NXia;p@*f0@Gx#5D&c^h!HG1A4{?5`$oesYc7eZ0V(nZChH?+X zid1+YyG+$IdQoFBvTar4wn}c@tHI*t_bs8Qq)nUs6>JV}#{!puJx4;X>mt z(G}LD%~KPJ;N-+AVZo$O~FS*#p1`lZ)CQU0A4O9^;K9iE++X!N8TlRcJB7tgEpp+*J$6p_ z$SNt!%N|kfQI3!*675!3k|xKuDmTS|KC3Pc{!-ZEA5I^Ml-9cw#0P65Ipn=7d>Lla z;?W6tb!7C#mYsB?lULeoHn~*TJ+cH>0s)%@@ zYXy`es?w(lnglE;u<%^pGUq6+LgD!5e(K#w{AUr~M0O)8sFI>Zm&7vvi$p;q6~kN& z5rbrrKPMM3Mk;N_KzB+>db=A;SS9KJCS6GEaPr{#-+p-&CV(XrC3GV>OG%s|Y0~=U z->bWiLv7{M87lhyM7lm zG<-Krbw(NSEo46R+89iwyG%v)fvkD?P>JuL6MQKaB6E<%8ZIt-;Mm6Ep^XsLQC-+m z;OI=&1ZNHr&Ul$1n2*gt1WEwsA08|b6KGqfBepf9E+~R#IaomBPv5d#w~*ZlPklV&;l)bM6g%_5yuCgNKY5+ zDKHR0DD0?A!mw6O5MssCW^c6%rMAzvXb!_{S#$Jq0^+^z!>!Xh`mA0Bp5ME(MbFx$ z4D1@WGawqSk8&foZxTxeTyk*B*g>7=p1KbL9-GIHTEsGWhw}D|FClrR*01vSXD+n} zIy(53h9A#Lcy?2DdYwY!+PW0BnnErHoZsg{Kpd*q!`_~zvSe0#J2VN7ZZpzrM|u|G z29XUMfZ7elxC(z!t6|7}t)L;ZrW&M%8_LDSih}6f@7~q|=;qHcBkdj?gfp7aFt^gg zYnf)~Vjv>7B(#6FMx}}8THMoVJTA@V>(u{6eJ(4cUq|frIa|lzFf_jZ-(mar$_EZ; z5l~{-k+*5GDyb#YiB)$8cGPgQh&lyz(t$~D_B;NCQhH$3yFo1F} zCruaSW)R0+jI6wpR(3H66MF?Pc|0QHSBkkv_GBxxK7wsfrp%nEu>dl$_Be6O}h2-Teh|!fE0&;oZ|t=_#EW z5irR`hDc=Vm>MyMoTgdwJSE$#-K+rVB`vj@G68nvPHSUT;O~bb5%S=8 z@9NQ8qV6*O$ZALqq<-Q6Kw57GFPC>7craauNt5DjN+_j7RsX!-2YL9I<#Pi`cX&aJ z`H*swcMXqeO!imFJ&cpB0E~(Wo6N3K5_h;d$UBe;J^Q(aq0A}Nf-gL30!qovk+rNW z>^b=OUCuye`nT5i!z5qE}LDPJ{6YP z7>m$bp&ETe)4}e>C0}5n94f*>olUyWiiM8vq%sz@2?a4yqPPuOW@}8vJO2RLtiT{a zGgxm!EV!A#8qI%Psv^EA0D{h$x#83poc|!mk2-Vc2*fIKEz=qb7|Bx7FA7cK5tN z4MrM)D#coF!Ry{=1EtU{U4B7Cwg|yqa6s(bs#VB$;uM0A9%Ec|TESw;h>3EEluS=) z4CiC)qxQ%QOAL)EhHY}HT-#Jhb0aCSgb7_7DfLJpF#%~A>oc@&0b3eXP>CD5a-nvo zehI5Gb`+8c#$>wZ>oiVLijjRLDhYD#j=bf6>H8i3SpDf>0RDpG^>ZUiR!y40mdGYm zB5n&b1+(qt`;`Mb&*B&UtAwKrK0==@=A@F$*N0Zs#AeaaZ?64jx0wQ*u2Fq&lqW%$ zxW_HoN?N%Jn%a|ERK{2w#^nOV6I((5NAT~#wjwd{+8?+QJ0!;JAkdCfCVsdWsGjT0;FvhcIj`+YiYbdgr1=PCQWaHH!f6{WC$xPJ2%G_FP zsT?ZrV%df<=~hN5@L$!p`VNV$qALxUWG`5oR;VB|PBL5dx0Hi9GwbP?{xG<}H@Xb2 zG(ujz^VN+Fe55{1^&jTcA|X-?Cyc8Ci_3VSUL!f4mg4w>-OqT{H^ZS@Z`If>v%~F; z7M8z4Qg<1z2J=h(_Tj|iAvd23`Hm+>=Yeso#|ewS`zb;~J`!1nwO8XoxNp+QEd}@? z>Mp1-_zUmWJkN-%miWs6w+Z&KRO==fg>Bm?gOL6E8 zwR!YrMeLM62u)jW4&W8ePcf+)yJ5i}f8-}XFw6{kVp;v|z&z zcK?jG-2CY5(%yvc_T8U=&~l)&G3wkJg}}?67O~~iYU`UZw?YuDQ1ruwaW5KxHiy9= zEmiEqzNMEol`|Oym{R6EF%Q*)$1#_X$44gljE$yl#j8>Pk_T9r?@oaXXk4<9X+}C= zlVU5yYjP{})Rr>6@g8LY(PTMiX-9MZWzpVCN*J2_cM)ZK;p1XuG!qP_r82C9t@7&C ztLDP;2)a$K=QcSS?1T0&TC5<+CG4uZs%_S)`LbVSm$%X;jVhl~l;!+*47axK)2Iv9 z#N%;e8medUhZZ(*=!!t~ghPuAh^nD=gAI+Zm%b+`J;SE$owpADNK@Cda4t66n87@o zcMd3%W~>9LnQWKCBTam<%js6<`vpLXZO+wB@#QD?lq%&c^G{$B4QKN_^XD&_qzpVS zsoDRm?nQw!?@Y)?^s!oN>wy9({3hwm4F33}gTeTPV~^EeAU+qs(v?q_?mJ7RKUY1Mp1hv5>x5uQodkpJQG$WpCcWZ zEJomBJS#2VLVTcUw)JSQPE6y0mB3;eEpS}b~El$vH6 zOqgc{kUZod54mv5o4!@*R9hC&%C~}CabKODTdmiWo;z{qA3RLD&~qdH`Bg!Fj7C9V zJ^Jb$UaaFRu(_9)oT*N(iKflZSiYdcjoGZ@Otl@o`KK}wpz~In2w3}QP0UmTx2gkE z8&7a@4_#2w#&NM$u~WD2N(4L|{)>=I%LRJNZXLl|3)~dkCdSY<4y{rZESEEm1w)8w z{i`QVk2fpKp z%bew3%k9qb8h#>b{$Tff1OPBs<2-QiG3ypSFk&j`2K`@;&PSXk5XYc>=movWw1M=U zqltxdwK?FEDm_|!r>s~!QyCa>^+=ip!n7ooKnJ#NUrY|(Dnt`Q?Qmstf__dZ2kN2!g-8vSE5uZW#YNC|DLyO0L+Hj|mU}_j@jp{&N zUW8rIpspS|u%ZKAK1Q)sp#yZME+oTfP*HDh&`fO6J$F!_ewEoQM2wMfR?kEox1oNW zs{wpjC)HS+7|K`hywmYwZZe#=HVUoU`eCqSG~SR;TWD5rtxZf<&5qt2S@+P&H3~{t4PqX@o#ob zin`6!`mBmZ54kY6{vK9f87?<*zHiBDh&ldecac7svm-|7X=+TIBM7~jTg7oT+a88xnWl!whkV+o%KYi z4YgGTT8c6~+>iIoWR8)6-$$xP8`q=V%#SL{js(lVwEK4tuNFfy&PSx&vk3Ncva9A1 zO1>?rg0Huf6f3VmM?U5aiaRAP_7o|4Dh46L`1p^y8ECa`iPP(qMQ5Oty=u_jcUDwS zRoBO_UaQoRA@S^`y@7e%z+jf6AJH^u;NL@$-{1MqW4E-U)r=VIiPbg_cCcMu>Bc>D z)DCgLm_;?V3zpa#7_QNW&Oj%U*55YV*sU1OBS=CEpVUTknp|A4?_6pI7C~+%#CIsF z;AE123Ud6p_`_oU?wPIrL4|0kr-@ks1kjOlz>@3(4if2G{+fCIlE>jzOWi$yq~g0o zmV!*6-9Ayivw*Ys^}9W}k21j6CVa|k$0$t)2z@Tb1h(IxOy@g4Rt!OT+Cl(1eBe~5=uS-Fw?N))uw1m#DTegCwC8W_99k|^y4?n=Ws(hg zpokc6mx9n;P7y~gKRH9e3fH)ln;ZmMG1_qL`VEW(9qF(uuNa2hr+a>-BsJnpv5)cd2OfxO+jL&PWfXJ9j>+l0^ByHVE<89?EknbArtb_Vvrlk@B+QzBwn!{=4Y| z1u3F3g*;**#c!xLc^UlDA=>X!>|Nrc?njX-0DA~}F*v}D_j5Gz!^WjL?Q-`KfwW5DvpwN|@v3&PrD zdvv#Dva;u&15?mSJq0D!4lihifF*kc_c)q%rVKv<+{U1lFr$~-y{$D|7fwFIe)?3f zwtn*SH;*;v9qYDMC;1>RU8&99*Xb>f>m7%*3Mbbp;F_XS^NeX(#&b6$)lM_L0*62G^c57~ z%MEhTKMk%D~9biKYfpFr@&so)Urr7T z3L{VL(Bm+G6}r{s=R0E!YDdRq{pn|Yf) z;beQwT`$A?a%vm{ziYmV290grehWT_JUZxHe+L6JYPqe=ef-MdhfZEw%C2u#{^!)3 z*`(WMbNMkP|AP%qCHbF5jCIJxNlTY7AK(ZA-x;-mnW~?*ZDbPf?XpF~*CbA5-^#}YfHU^(uxokZaj+72Jym=)$axYh&%m4L z%j+apvJ_TfbXumsU$#=^_$=@A@e?hFFgp>U@TE(ipZ_$^kT$wxSP@2?pP8?0Ax8~X z-mc3W0yk7e=@Jh(=g#r@4=x z{Wfx*v#Gi#x}W{;nTJM(mq0}47u`X?iIT?Hs@BhUmoiC0>H8jq6{DnD9)|)&v_SzX z+;?C2AiGxvpN!RJ`Mx{YZO)+}_aI+Pvj z>aTulA5y^oG7wv=*!aKiuzZn1IrSI5?ppHXh3v7=H&Z`j|9go`W;WRnNi@z%*=;+` zSjRZ?9iDR1xt5r?F`(4vI(qVDt}}kcR5wTSY;QbEQvSSx^yqry74;qJanK{Szf-U< zbhz4i5C`D`ArjvuhR|DMc72|_bhmKS?i2`bGDHo~`(8GSFJ_i1It5995i=?0&x0zF zBLbsQ1^SJGlNhlGj}*r8`G=YoxzeDVLx&J#1z~~2rfCY~hT}oX9sLBI=ax&xe zlu1e_rM2%WYq~{W3ppRI3LSt(0U8CBEAM`k$ErI-v;W*4(F%0W5mj+gPtfhI8OgE) z)BkpQft$u|i!<4MPuF$jg0bt|ca&tZS~tdNooBB;J@FUu$Od(D?T>dp@}_UmU%+g+ z3-oevnYxXdG+oLV3|%tc*A(R1w*`s@O8e!Fn+@(R!YoqwC3MP{kf&Xf@iY9_h(p~W z)c5l^Bi*IK3j1_&)w*!Vu&e^3?!)a+#q_m2OeR2%0$IXK@!rv@2(x=DEC4U>1Es}y zyc7h+-zB64sZuwTl@}B;jr&iJuKx7y*gE)Or$ta_ix2Vh+?((Y{k0{g4|u+?oR+}K z{07_P1~R8*544E$4dc{;|TLea3;+4>q)wG8mLN5v<}4UbVK+fxC`0<}oNnx83juKYIC`i>Q)?_qX_5 zbMLW>hdbTZdGzFOW7OfZU1E*zvLL>WOxTK-X2t`Y0~^STmUue_whFL-uguK%ruhRY zq+QU`=|97VRden02iM(StNe>~TlM9|#efSNOGM$jjbX8fnE8X$b(-|Dcf6uuS`FH} z-Sur3Sln_3!|6qz65w}CtKRZ=FzV*Y_)FL4^>vZl_fP8Z=b}$utJF}4%k9ST`@gJ_ zT{fhL@2T7D?@JE!htDNjfRTwz{MIhxuG?~9fmXZdVsd#qbHZ>GPsHrCWfs2r;+f6AVE{hxAaD+<@X@joA@ zM{)ybpj3^pGhEkz4c1Ew#xty!vqJ@qRe?0@Xj=WXYT|+%rB&&LVho@CVp-r)tT@CvFz!D2dMW9>`SLo@bXfI7e-egwO1zL*&(#pkCkW`Y63j zBRS+wd9L{O)mf+C!C!fAU++5W&6ajg&pFX2K9&CSY{S5dzq@!?>M%KsHs=s7f zBg@@!>;dm$oUYQ{ZCmO$RP&~2X+j`YtOOSk7ZDSYihuwtqlAOKD-j|Ga?G%3nu!xl@3ab7B5sI1c@rt zp(Ij?na@Y3bNL9`xTI6=9H733XM^Dt1p7E!t_P>#)%j(eSGi(9MCozKnt)sr^X~Kg z?ei^AKW*T3*$7|A(i=6A($)JC{LGGuMn;!>+g30^}RK>2f zx}5h}-gom{|Met5N2cA~n%uOKv(5{;B=+aqpyT#{hcQ3oh<-EG+NfVgoe!;N7k{1G zP9<$#+O_+-y@SVl1P>YNExMb^X)!85D5;&%mal8LWw&JDQ83B8bzq!dokINC1_3Xw zyIonE()vdFV_C8-#&bmh(BsjhmK%a2?8;w_V^b)a4jf5YLM`UPSE4C0u0v)anpkO9m5;i(G+^Kv>=KH2(mj+ zzp}hAuJ)UqC3g|#UUBWAc7sQO(MBj5qDUX`1RUTGGv2&IG6iOnlBp`%h|9vn-laQd8WZKjYVXSwotR!6Y#c2d-;1TW@0eY&!f;u*Tdg0f%GBmDeQSuP77t2*yQ4fbvy_Lofc!8>xrkMXPq5X9 zSS5qy3yH1%iCww$LMM*c3{f6v#}4r-)7V^IM%2xN9c?X>k*`c@24!OnuT~=uRLu`h zmX}}0c2!dib6z!1w9Zt)FBA(=fi$-b&&|iLgrx~=sp$&Z!B_7M&G#|x(Zs8XwR4Rx zMT15T$-|h}C|&A1Z+|QQTR@6Pwn`J2l+_gAja@^Ik}4LqBV9iW(jvXc3dL1J zR&QlhxM+v3qwgc@mc)o0iheK+oL31@A3|2cC1F=BwBQh-uCg@r+M23E(GgAP$t% z+qya7%`jOIwYiXuEL!Z8f(jRA-_CURd?1qF5dCygv1VJS@VMDn_UtW4eMm|FUd$3* zUVaQE`^t}`FQZgYL~JhsiyrC8uiO0XVKei%Q$%H+x*Bd^&X>P4v{nM6N3)MEgT;=aPkf*m0Lj%vLQ0-Z= ze2<1nyZ0^Gl8DXQ+Nf;Liv?VjSY1O8Y_B9@l{6lgJN}(`P)+HxbGl+#HiddpuM<)Y!yiY22 zLi7iff=EkQ!eKHKXr6aQ6o{vF)Pi9y^MA^E=ip4DXx%%R*qqq5-q@Zb6Wg}!-Rhx?oB@^V`0WI`E05j9RFO8MA`UC zSpz^aIoM8CQa_9t2EJEBlv`jx&dltfo~B?W9zrEE>lggdP(LiltmT1nhR>vYDnCuw!ZM0aClVYW#W$6v&pO7n(zdCdCA1c@e(Eqb-pvx(oMw0nPWOSGvu$V=dYZVLP2$TeOpp$25_4?y5; zWP1=n2yC#(3}}!I1$cYl*%`V6+NeC^R^H98&smKLYD>uliOY;X z=9aHt0xp$<5~Ou3>Y-n)ZMMiNQHI`)%<#%adadjTwZE?)1wVzN~NFAh)?f4tCn*YXb?22)J%k4CisCDj`)&w`83tuhE-b2}>elvy zW}Kw^*YLm)y-|0;;ZWlZ`u!I16I|oU1cwZvYo?PPR#s29pf4fp>!f(q+AVdVtQ^+y zlv(lu$;%Xn;aqWbUxxi@WABw2N?AEtXxu?rY!vuYGPOj9Tw)H}ly;On29X&?cxpEs zMMFp-6>YA)7CMcMcK5={Hua_EYJ9B}y6(!#wn|`Bp3NsEp1iI$0S&!#O2}QWmV|GD zxG$<;$Z5Sf^2?b!*Vb?LyLl3^!dDUuEJ$4 zOf@cJhG5ckQUn@{NhHoNZB$U`eU~ihlti+Vh>FVSa=)|3XNKknaUYZhn3ShB1MoEM zR-fi6AGJ7aXHJ(|J!AsE>b7FF+_s{&`5u5)4(EyQb|16u%f8+vO|sv+F71zOK8KDG zQ^mW}LppoUClxJ1^iS&es6z#V_t>YdnkfSYn11!VK8O`b-AE22oXp|JoQW`+q{R#Q z@Y>R}@x%x8g>047NI#FFH3pLM>Bv=BVT2%zp}-@8Sshp)0W!9!iO&X#n1%&kbJW03 zW*;bqf#ROMD92CXox@B$;C*(>?3U{RlkHG&E3_9<5ASoxB#`g(*Z||%I(2D=L8A{w zY4J9}91KOftQcJ}43m5f)+`q;QoFP@t?L&8Uxw<;5X?jvY#iIYJmOEDAvS?Ur0?|^ zt5PGVt@7`qd$f`1F82tpeV@;^kwIY9+w-G;tgK#|mA6#GYp_?;tJMOnJh}|V)Zlu8 zJW-FJ^qzuDj$$BH#-uR`fRQ^gL0*zX<Lr6lx{9N32msu&}*>Q8ValA=>o-pX{>zCpxLn({gZF_ZxElVA4|pj z3^pf94(DEW8?TuY#L)s@Aq3IP(SJh(FyDf#h%#koRV-fzv+x>Lvq=u`I}eV27iUng ziBk2GQqwB7{unP*i~tG*H^5TMnko7Wo=PwV^{w26%eJxC_PQf$mv0IFgybl2iIo`K^LDh)aUUC$`dXvN#L z-nJs+U;-a4W{;1Na@2Ow$-L*(}in10&0pwnrh&rQ6PruFc@eutZJuANJ{DNS2do)5$oHxPW{Mj^`MC z(1$*|51L4w{4own{TNS==v+(a{`6M69$Lj;`Dl>Gn3Fo14U5T0;3Qb@?NP?4!`i0g z3I+d+0^}l#&Hw47<|9cx_;gsJhoIABd#KasN8qFP&f)GoTE7+y>YTXx^Aq7y=P#JR zN=9+dG}41z`>W{@nh;MlsWK%+$sD9ZmXU?jS)y-rt$b3B`p zt<4}qTc0*zo2oiRCFYBCp8AgHTpC(0Car$ALMNx~_;2lld}58afQ(&$+~ray-4EvrwP1Y!o9%erhgrDC*rKlwol|o-h5m)GoI)-l7LM5$O+v#%cR-mDH{}Z+0nj?|VLPo!g+FPv0oh7~s2Jk34kKJigeP_c4!=Dj=NeBYya-x9QsprVW#4?9Vdv;67i_R&pRtMIQ>AI!IwHv^zHlmm;F39jCai=Q~qrw zWCXHJ6|V>QK6CH=Zv^pLCU9pL(dA=YN`Q*e8A`$#{_m4b#>u!c31y7XEQ(hmZi#6O zi$JNcA}oJYWuohxMNvg<7X`rn-3Lb0{`yAJA)J%T3*fck6I;d`Db?$e^ z7IE7glCT|h(>ujA+x9!5fWFt~NuPxydUI~|&Y0UWvXuCINvREVNppgC#pFEaBq_$B zRQ_Hym@V$NX_(Jmb&HX~TZ5NS3@V8pV<*K9q+@;b*HRZ6)oY5(^zv*jL)_hT^#=9# zJ3&p6aD~%_zks|C5Ecp|Uce(tdWt^HrZsEWR&VSv5Nw9TI4?0Gu4uVTdBWE=qym2K zHXmO?Gc@mRRw%oQ*wzWO$*k20ud`~wOIW)0AE&Td?!mV@!nPPRQDzbSFEF-b+jD>C z7<}StMLgT%8Bfrs(qMH!k@s(A@iKkbus2ky$;hsn1n<9zdOCLW1tAhwxMZ z-0$rt^1s~N)w+#`iwI727hjZa8_6zBn#Ho&hYXe5?FU;UJuQF&L)p?w`*wiQTL41i z(!;KRy;~Syl&3~{q-5=~+4y%ok^5YNSfa!T>*llc+{vx=2}7v3@KD(ItQOSop?Q(3 zIG(gto3xuenHJlg4xkv1XJaKVQ^nuc?8^-fy@f~2P+t`ufx~d=3?De2@ZfZ^tbC4O zLrh+bSdM50Ve~H9*i9Qqi(E`MuiGe0Hpb!IG)y_KZ^?)J-AM9b3%pSVm^p}~)39ee z&E|CcKE1Ue>{z7(SU{-nA7CSpN6p2cw#Vvu0~p@r60|<;4XpF$*T|*VtduW0vZnx$ z*wsTzvZFD^IR*roGA)bsR#EKMk?|%4X(cdqPh#3x8g&Z^lVjW*@|C06l#xvevs!1xg2e`W$XKfaX*2axmIvn|oA zuw`GUw(9$nfx1B>H&~pvYocB+=d9oBBoBfb`BeoTnd*P}V1*zlkG9#wQ*~fIyG5E9 zKsj#r%eKMT22*7}>Gd+fM$uMe>G~iOJo$?35b@+CkZ;uPWkh?$m3G2sKie_3rF)?t zs#5&8kZ)eWCqy9m)BGUpcc;MVgjsB5dMPA^7B6a!fC0&#v3=8MOp0H=RG?1!{_m(v zNJ@FMpm0eY3;$9feL@Ef&}xAK+90(0)Xx2y=7G8a9R_TysGT^Te?VwTdr-M|Gz0S~ znX3hvr9-HdBfltmSZIW>lbJ$2FGX82^u?>cJPYh;73(5#~R|z$eMeZE^G@KVX$nJ5yTQ8PgqDR-)p8bX948 zLV_^ZAl>+d?!$WUDHzr38l7ykt|P7%qirg@U}@UbT(#HRnnT~DZV#vvBN<|7qXZ4W zojlig)ZCn_RbZ3;hOC~Ll$QVetM*XcTGk)}JT*VJQCjOT!dofhKf_39e*j6n&4busQ6la&kl)i(*O} z*smw_DH$}K$4)srUF?g|q!I3m3_y6B5EY0WE(_+Cnt~1<_7Z@##3#V*PYs!24%$3c z;EVM!bIaXyOZnbUM+NStcbT;=&8xe&KRQ33c9qEGV0_;j4Sm1In!N(uXhyzw%QU_c z8~Dw?F6p|l`KjLg-a%fE`ne=I{f&8mCspz)Wp@Li_5s|~KH4t=F9rfxz0bic-|IaD z$NvDW)vuG=%@HL0V~qk7`?FR~PVbYk{nPz{g|CZNdM-MI{9nm8MVJkrXHIQS{bx?; zT)RT>rK@t&cLPMONP9a%nS_WWc*=<7Pz6v%P-06L{O%V!>4AGhG?tDC@%%r5J`wBB z3w0%&36;gX$w{awh>Zk0kS{C(N<8@EWlM^O{#Ub&&_CxFC0E-FzQ6iE58t1!Fbh9R zujFonc5heqePZuR2n6mqpXY!5{)k;NdCwIhG{vJb!ZG2Eo|BXJ1kW8|l`fLL_|@_@ z+0OC}_I&hmUE)c&*zI+jb3^tG-0FDVp7deV-b=lD*dDuF&A$A;!e8~ZNCm1rSJQX6 zUZT2fZ+Ugl-sis-?=V) zXl<=$^Y=;bn-G5}Lq4GFUJC@7mz`=mz1=$ zVD8cJdGN)JY_a-1gb)PAnPV|0CchASfn`pmK_ZOj=!zRN)fm|ojMPfUDVT@k%$_2Q z-44GCa4=x9HCzHtL5Y}&wAh)M7&rl3oUH$*PE15B9320iSeO7hM66syT8Z5nSY{k7 zEDX%-99$eaMC_bI9RG$>Z0rooY%Bm)B98yo;J@Mk0DyssiG!1w=>Km2f13Z#SN+T5 zWKE1`r-S{k{KPJH5ikG~XX3QxPvBRCMssA?FF#gP;Rp%Rx)YJ2PY^?-vLZveeY%(T z4D1A{Ch)o2iLUOb@Ux>8tV?1~w*u=~k(y{n&S*7ClqvUFaWZNu`cJ8c6cIBq^ubGB z4?LXt*nB$B{8;(y&dlB2Kf?h2h?7Zb=QZt}-3nW<7BwrNz2H7Eh6)7iJ8CMKo~xD0QGnFq|LP{pP@7AH~t4T}g0*MW5%la*#u@FiQrr`pUQ?I>yoijIez z#-LSpL(Kalv{8Ifq*9F~eIV+>q5qbN-?B%{&lkxgc` zo&|vKJv33+%>G+u-E#e`gZ6T%TRCKX&9+Rt`vZ=X^zw<;D8S~!XwX)Ymwpp;BX+~(!6}782o`9^4W^iNr&qNaKB$E^o zHkG-sBXcWkSMIiC)Q59UHf7GNClWW1^jdta=A?A1g!NN%?8`1y+ykFzWK?%<4yh@H zZshpNw|4&^^#EdRO_==yuKCw!wK~uWZB?4!L$W>C_~+fK|Gi!p4RU+Z2h`Mtc#a4z zLI}u|rxyG>jK}$iMqkMd#w+$}c#;5V=xrNBa(C2g$VU`4MPxeCYVv{a9dfk;4;>M1 ze0RWwU%D~7aIzJ98Aa1FlMTt_0k$L3RpC~o-s-0ts+);`)EDxdM-&~A+aDl#v>K!f zP(<7wNa8T}e!zJyzWN*&=sY@}Q+M{mmDnlFpxrkn``4&_H9Typx>lO>32k=u##=tYjHm=CFVw4ZYqz(9yl}S z*PDaU$UzhV8w(FDfYir*Z3akOMm@IGN6<20%8tFi|G-@(UbV-S0-8V}nn%JoUJQNo zA!V1-Qm^lx5qDfVhM$viJXsS4n=Fj3r(NFi$1k8WSs_n2taz`Y9;uathUBo*ib^b4 z@uCPkktrrBvE&AJcD_wF55W{Y*}zMrnuAVsdj4s$ak6Mm7SENJ01qfslu-2ZF8|eS zk@ZmJPt;8Lvdo=q`4WO0X%#mg`{POk;-k2x!HN4H1XJ^^G}RFEy#ot}B9CO1S$PEw z-Rk*$7$mt&yy)j6Mf7x04RMvke9Lh~b)rbwC73FUOPTX^X=B;oY5Bvd^3Eo@an-#Q z3ig_^)4tMGO#GwCXhdMgF#xK%lRM*Rax(JGxH@>K>mFS<8#UiMVvLs6=eIrA*1g_i zsPZsTIr@BysI7RqqyiPg{b(wH&}DNW>H6ngCQSy-dOPm1J49kj*`mIA#6e!WWGTEx zqf1ZY6!xSZVN3>%rM@(0^TWqpe`%AssYa6I7^Wo+N`Qb+jTx|U-sq|b<`X^RkET3V zsX^>7)q!^Q_=!H*#=27JQ#j)oCqfi}_b!zZvC*0r(~~0h{7T>{zV5ErIz~zon^;@Y zn93IK!b|(O`99u5b#T2wXR-N*Ko)^r;t<_|aS(NtpQ22)CXwi?vNCGS84t*(IKiB8 ze)bEHs^(rciwL-AjpEojDt?rBJXsO;xuLQz2>FAiy|;w3f1$oKEfS%Q#k8(-X#yTk zLBk(XEADqR_T-ItKKu2c?)kXkAw3m!fr#NiezT+kZ~&$b9?7DhXT zRTR{dD|38e&S$7mXw<3Xa5Rd%)S@G{WR=OtcG@hJ)@$GqjEStAGJHYsz*hZP?S*S; zo&mn>8J@uztb0)B#DHs~z?YQs9R+uq6qB=(Dr2iTJ(GRQGuFmf(BWW`Na9qSuUY;;@$b92www7z;JY z+c9aBfi8xf$AT`7qY=}nM!%n4hQnE@f@(ao%@i0lG04+aKBlF}9;0Z)+cxbH%bOaE zF1))CJ}}SJC}aKDzm~6xvXnAG#S;LNS?g-K$`6?)`4erRYAlSFC!j1#A}*L|3T1nH0?y5PIhx}SVnF%+b+Ep9=t^tfo5GYN`Qahpw60E$;BSC9p| zIw>%Cwjz0y2F<0j6s0NOKinv*iYV}j_<($(rBUz+mk2SdinBZ|VEs>>3N81~2=PMX zpD@cQy4mf{;;X)3eFhKVXfjER&X~UtaByRjdGn-Ple`AlWPTcWG{l3mB76y=cka(h zZ{1RbjUz95R8WdPZiTb(QVj&cYLgEvp5z1LKsY;5YzQL)EfYpxpVI~uKwWSI`ZR+OSX7S<5O)I@y@8|?mVP;V(qz` zgXMpBBzabAbJZYDW?pA1h@uP>OUwYCxX_h|P>3f^g@+(Q#w(DRh-#$M75tzXwyr1h zRKmWG2xPqGYJVOw@`}ONx8CtrqMVkpn8Tb)RebX**WZ=FP8Tr9 zUcQ4uD|m`&Op}?26AT!dc(D&ieZJtMk<(9@lKf{$j~uWl_9f|0x@PIT?~%CX)KkEXnw|Ka{dk=PSH& zQT|yiD-{@ZB1wWxvqnb)rhqa6QdP%asnYQD#>C?X?lXvT@fXG92{A=w?^bIi$F|o80{SJP+}x-=5?*N~NCC5$Ke>!D!Og;W0n!;$ zFbu)@cOa{1S&?icUV-0B^|kVj$GdTTdz&#c6lbL zOy%|2m+szGDqmyqJFPGE+ad^y)`WpfI1Ek|d*2`hS9Cb?2nB^^6}Z|UO0*=YrErF+ zOyp5zu}A@Ptvjx=IcCL9kOuSLzmaWgXFWhjw1#kSaI5@?dqi2&dYQrfW7NgdUheL= zYQNiQria<8`63SBlrK@&Bdhp!c&_jp0#pP49)skyWNIP9DS|}X;S6mR)2k9yz~L_OotxRSACwrhejvv3(~0ByDf|BzRuYgiN>+P8Ce;q-?h=M8WS)0Dct}1&o%bs zxJfhLXfX&dc$;x|BTk^ZXF&apJdNcsQ_Cv{(t5{KE2>36fk9jytIupENcr?=iP(a4 zg)4WlHHOf02Ur3g;y*d~9;#Ywpe6WNNeBEYg%pnf^FLO>5g$5xa35Jm0_2Yn$$1us!z#D~Vs`Bg@KV>vYAhwzeDU5> zNQaWIKSgQRtG`LKQ~A(lXK4~ONl3api{;7dPBVLN{GKj-G$hX<$BV_N3*$AuBf4od z^1q35@*hD()pQTLk?#`;gNi3X-r5RO^eZNK(Iv=upC|3mXz&b3bX**&UPUj*W95pd z0y_d4jU3LPHCRH9kM2|BF#au7EQqVTV2}7asI7q=GUbrP)mPJb5#i!FO zMoY5ZZRK!TN2~Ojtj03T&uM-#@A|Y!;C26lPfyqoa`tp@0dHjFcG#V-R2`x3(<;c7 zR5W_VFi4zKG)mqeC=LaAifyO~DNy#;-`HKS@b9@xra2Mm3pOk6s0)naN>(PZ{3ftQKzS9YA!WWe!e!Q z@)xcq$(WiS1gfb#gT>4sKqvD18Ma;Cp8&3t%D+VGs%rXVyU_{Lco=dhNN$}r0Ko((aL=dFFwLORhZCr zbgvVQ3}~e3_=e&T$`W8~LbA*p%E;e(2f&faxAz&#P^DQz<6>Z`7l3vGZ8k9n@xTwg zN<5A|Ryi55I0IAhnFOhjmJx$)1gY@C{4I&hU;V*2F{ayKf1+0qsRjF5i$M()DJabj znk~__58}P<+)tjlp$>YFlGYX&!^KPx#81IXnl=0)^ZI}pzx`9cZhwui*LGb9m`l~s z8Tu8}@E+UwvvOVab|X>+xT+6z6oBr&+I1X${Cv3iy%v=0HrX={tC|scU)C#8`pTIfO4Y&CnxhK=3UK$+K#ScdjC{?NQV0nD z88}V(9j~TZ`~q;Xa7}xwyu^HD_22$Nu!G~?=p<8?c^Yuh=$LcDkYZUy+8L({uz1)o znoJgXT5$N9oYlb?Qu0CyLJ?xb3k^W5S6^=ZtyxS3-=Dt<1Zz^qxgfYrn@6Uye8e0b zknD5yTpe@midF~NffE!Vd8$>$^=TMpicS;{+wM8!X`INk6jqn6VQYCqh|#WLD|!8h z#5|*t8;eZ8_)6tiMv!ES`zBL}ydpN_9VRFlrRD}k^aSq4y=r(#KIfZ1`Wr6BX>s-V z9FAm~&&Ej^y<4PGOo^Ar)nBG>vhXRmp{K`HRZ)&+)5Q~nfC0u3r%6DW6y^%Mv(n%T zzePl-LJ>3mJxyYRKM!RxQ(`6m&T=`nCDu&{=ds9OvQE>qiRCD6sGQ9id~JZ_j_3zN z12w~{vlZpwIt&)mE65|FA>L+_bF9pH4mRGBrKMW5bf4jF5EZjzI zrhu&HY~6MMKltj6PYpl+p4PrC@GM8m+#PJm|6_2+d3cSk&~`agE5{jIE`6b~VZnCT&|2f#99w5inzF!@hm|Y1s4nL1g^w4O|Jif}FKtq{J#)6Es{C#LT*Gq} zhxYd?olM>iD;W#v-%Lwx1LS-yltvW?X_d$IyY60iq#?I8W^kE)Wn~op>vA}^aV*oQHr)4AMM$I7oiQd@jGf z3C1jY<|+t-l9eZK76yevON`2XB|9Ypl>&A$kNvPeV0rBm9dbtWQ&;diCDXH%#q*KG4q3iB=ZMsS`=iHn~ zOZH>3Pg)aw4aOdU}IrIa=N+f39+=J8%N)Z(@KMURcrg6T(l84WPgwJd` zn4jv9DqUEip_+^J>?gaFN-BPBLuptjA|7WiT!)+9+0L-`*H7_aiX;o(zQ?91_$5Tan z2I5T#L$sj9lHuXO5IzfhO5|pYL6CbRL0|qXtmd{0!vksRm;r?=PpGaj3l^WIVa=UT z9#R1R&1>%^SOHS^Lmw9*-eVsezxr{Y34iHhpL)dNyFPKgoZ^FSgzj!&I*>nY53B@< z;r&k{;uZPI0hq}TLh>DN`&p>mhuYz~mREgnvE4zgRBFUu%`@=`NiGJl=APXCET4!p zsR1sE#b!Rejq~x7{H1Z^sE=`{f$)ULxqFX%!HY-{CEbVf_&(Ky71f@G!P|rvo7CME z5Ezrz$uz%X++3we#o=M#4S}d&`~J2VZ~6KV(+L*wZ%|JauAl=f7il9H^y?>vzwCO9 zMhf1G#jZ4mE<7A18;h*Kv>Y$E`RUE1KBKr=Hg)T+jnzV;R^KD55h4~>Yi7?R3l;Iq zW-VRFBvTKZHBcpf5W-TX?L~1Lj?}kqLMUKr|CzSMbe_@F0BxQzYzMkUFARCAuGG-= z2UB-^WF+rOIaYVDd4C&08UDupewg!_X7aM_uo~>PQ9F#Cu;g1z&dd6>A(*5QN~!3d zW?HPGnJ_^a^Jr*2Ajl1jgv&^M(8J z@z0&U%ENIz#3h!$DF%p5=0o8FO27n2S1ft37#Rb6zh)v$k5e96T5wCb0wf3DY*IMK zg*Hs1#eX-JQJYRptz?gH&2pyqQPZ0X$FG(8_(BtpNF~Y_)K-J6`=wCU&Y@ z^p<$ZgFP0VNZTqsmdZ8e#7^CS?l!}>lZ2h0A$zzJnhOod?qZ3s6>NsJtI;&s;Q&;g zkofMyW;|*6IB>BT(T=@5qzYFHPCa8?N2$BkQJssI_TuIwmwV^w6J5R;7g)2=zKK2L z9E0U}8iy=RHsH#Y<1orzV+E(4=7#>#uD#KQLz=n{^!XLI5>6azYaArL#Y_(5Pm7r} z$Uas<_v=28HV?;ZW72NsTs> z#pvscY0whwGhlBZi%Hg>+1jn{| z8vj*$(!sf1Ws;MC+cN~@XX=VXP8yzB!)dfQ{RsKWz6Zh;6JH83q$;gtRFv3L_;66p zwOFF85eZ6|3WikB&AeX94o>~#)g~-=mnf@Gk6j zI{MWGlHRY~VDxH^UMkV7i&*HdXYkXaS7J~!7QqluX-J|F^>EEEM#Qw-FVpLho|S+4 z6W=_NP!mS*N|)JCw|4FHuvkK^$o%?Srx=|!pwX1+*j9fSB16gx;hpe6YC8+ zywsRWoA1C!deNK*I~y+HVk0k2JHqul+^wW@*u#ETw5c8p2P>n-3M22Oy%)Ts#pqhL z71if#sCV*jFNDu;4+XxzTd)6Sp}?{ORq1OiLlW#2k_p5Rk)p8`_xh6M(2{{+b=)u% z93z{MQUi<1$pkX0*rqmqR^IRdjily?L6PbYwe>6vFRxLfI`%jrW68?NolZC-o0KRb zQX`vcB!t-GO4=n=gUGnd(H|_K%8A^Hk~pY0D6X0uNg&_7uB7ppG*U~JY zc}^%DY03&X{_rF3BknL=8xbgg+zm+#gPyDHnIjTo{wytl zs>S6(rGgm9G8O?Dh>CzDn^)U9!0HFQ+M=GG9QseW z=5?Eo-cL{w!o77wv#<2!9rbt4=ZZY#=f5@ZE^dVW@>+#eb4e?Z(N43@V!!wwqklxYM=HHfioCkg8gH=$eTh45Yg}B(sHfMF<3rT5 z-sOW(shfOg3oJ!yKX)K*iX3UfJT~h{>{Z|<+M!Z`T2cJT(DlRN(0w~2_b`X6pqCG9 zTeYVs>DQyZZ?iK>;EKB_6y$=l zs`*0+T7Rfl1edi%mj3n?c70)UC|JS8+!TFDTuJJnM4gqiToaeP2wON2peN!o(3)q z=YJ9~iCr3)XdM5E)e!w3m?m*qgA_sQzmORwqC_~&{vQCQ{{_6jGR}(yF~^dj3g=7y z2k=7vpTLU<#)r?ObcTf3kMpSOrW)*D?{D&2fZLM+q;mgow_!`9efvk)7i@;%dUZ#e z1!vNa@@^M8*dtQ{$`h+~gi0#TSpI6n z%u2d8Ur2i?a14s*SVn?t9L4X4RRK%sV0G=(aZ309UY#Po-;^|JYP z^#%74PydsAfYId;fIhzz{zqLj0ktscm*O2+u@DJ95wTbO5HYD&Mq*Hehp=I`a}Dn+$xk<=SYeXo>ZEV$?OeaM#9lxIv>X0TT>7WCd+1OeCiSz$k1~VJS zKNbG}6JulkA2Ajdwts#9dmal52kSqH|9|Vp0$^eOe`*07|6nR6uK$(@_>YeNqZq)# d%Jn~s0RSehM15TmH~@ehzzR!FE+!}b{{b89?s@F0qktdYytwru5K>o#`bWY*;o4Ou>>6nesy)@C!oGrZ(!I^zwN8? zu27kXh#7+d*!n#`iPE`HgjracQaAKVQjN?e13eWJr;O|nSa2TbhiAU*V?W=oE&NBd z9JijfTNMonKc7HnMbADpWG1o{8Fp;$NgTgk--dwCvA=?90L7+v-NegO&K00c)f}pDgqmEJCpym06N9j8>Kc_>uC^&|HZK`~ zrs`f-u-B#oov!`o^bjYI@D0mTTJRwT3N^NU^IWJrj&10sg#{=Q{FHNZjx&!mS`QU! zqb@Tg&KDjR!_YQcThqLTN=;iX#e&fonl|QB>Nn+*`(4R%ov|mug@`(<^GL?0cs1~S zD2}i)kUChU^sJQ+D^sT5qumMZw9w-)#c1Ozh%ne}@Kh7v^6ZDobIJM=%?b_`+!VaJ=QTp3WKis@cs^%XN(7$HtH1VryPDtdU_C{RR ziKapfsDcQdkJsC>mL-wV`BvR4(Eu}=m8mW~n2kj3Q&lyxV{>PQYrAiVXdTqLcgHcdRo>u*c;aIKeFQra1LSnJORNstr14DOxmna=)>21}NEQw8&5v1yvPpElDia}w z7`x`3!;Q)tYW_=wwY7q-*$G;f0=6{wv}0a>kg2zG(UnDiUwrp?krW1E)rexz1qR&b z2ZsbUImu?$iqv;_d)B`?%du5!cTA3hmyba{>88MT)4-M+~oZDozCYg0R7_fTPj5=ORXlzyLby`Z}N`A6Tn^l$Z5H0t} zTuh}@|INa2$c)Hb^HBTdOfX$vHN;`3tXpW5xb#>xXQy5Q?<}CkJ`hj zTU2PeqCxUF=L58DY2D4 zx!dpk&#e!fl0Uifm)N3XeqV9P`r?fkAPDj`^!Kih=<{9qhq5owIq?~`qeH%BeaP7= z21Z?sVog>XD=b=ZZe_g{Jcd0k54TCL&IhG5MmmW&VIOTT-rOOB8 zc9(P2ar$pA-`T5WmWa}W_o!?77HW4i=l;PwsJAKqc`p5#6FI~jGXRv_k56P77HUVA zyEd4jrZg8W_Z9rI)HMh;l|8=t$KHbaKBxirhNO&cMG!+RL@7l*SuxwibMAvXtdj9(oTu7(Vq(ssF4$jwL{?_5uSLJC0<}NIv3zU$+agq+$;2Ty z%H_U-2*rR`#=E!~bpd`O>H+sV63dm6<(*2r`*Pk_zv3T9H4q+TURAOBazs*ChapyU zD)N-<3;Xb(W+i#(2xP}*;eo3#K|&7*HU!GKWs!hh6!96Vh@(Qd#$0nkr-`gHviqMU z0lfg-ou}$T8nt=^^rpF-jNd-!;_ty|R+j>eqeK^Sm!wXdQSk>o1c0nh5NWTRnDqPO z)FgHNcavxu4;1DgQAmxd61vu}5{)2)O*#oS&RC_H423j3E!_n4Z zvefUoWr`t0FO92{28=!*->x2=<=*)i@4*0Mx#Nj!dV72}Sk%-FVQ3Qk#01cU zI-G+93g>P;8U_-ib9MHk`sWdo%2;OR4?brqBCzNsfhF)X0^Xl?M<{RFb_$1%x$^Yv zescC4j;!8}raqLE|*sw5G$ZX;l_ z$4a%9gh7KeSjdaUG|4m!aS@bmsabzT&aj8%^?!!~CoaJ1#gv7W5BdfDoz4yb4;Co& z)hP9+HATGvHBCAiH6RnsC&sAh5sO8*gJyVP%k2nQG+GpJr)%KjEm$pKn7{DEi%S%O zbwSh*mZs|-SCkJr-r|C#c!ZB4far$`I>Ir=uf9po%FKLB6sfc{zAFGZj`TYBYIkqS z@l;lN#zk**QXWt$ZqYxrXy-mZs;M)7ao2m<3G3qLAc;pp+Yg%v}|mLKIwJH2+$5 zP!gqJLd7Ued6?q!HNOzc*+3|3!PCbfu}!*1|5Y_T59RsqOe&vmwTH;nK!v+XgZWeKG9T5|%0VKb#Y# zW@`VwSQTX?BZ$;U7#56_ZYgae^C)|+M9w+A?eVza4t2Sd^ z$y`MK+0sc;Zk$v{fA&A*v25L}xUCk?LaD4Pz2GfeT-*xPwGHrnXz*vuLldi);grpt z=E58YREExsL#N-`k4S;;C@b9YDY3`k%z>+-WrFh8TidZFf_uZ9;++4nVY~18xh+88 zTzqB*0c3ZzO^+|lv6E?uenq?gAj?s1*qeyXg}&K`Yl2RaG-Z|}i^XYUtWb`IN%);F zuzNpEQV#6_a}F-hb+?^?cpg9)t}%OYY;%Nk#uM%$#R0!oh0=FuZgE9vU|kdG2-Hd#Na#~9Ii z<(^sgZZ?8f(dB7vJII7QHjwLocGTvZOFM!-^W-7Q^Oe;Rj9-Yj%U<#AQeXUZ`dEtxh`oA$@&CwfenvrEy) z0&HGZ{VXB-)8y5luFE8@!^N%3{nl(HS#(@RONtDX`n6EfQ|lBfpyUf&JA(t`V zSP)EU)$+r8;bygO@RnZC=}3)Wo&{{o5;3JO5^#rkCCDrjOw?zHBU23xTqpi!KU$kn z(4#!FHKwJO^OZHW`1O)1nTctip^1@Qa_BaA&lKIinTh8!w`u*-ub+jF9pJV18ebptAubkt-o zzY_Tpn=f}Yc+!lAGhd8@8tl`gEyS2yXHttTY%)nnis!zFPG9H{XiygpS z@}@3oEzzAcmK!*XBRFNVz`Yt-Tt1@mcrxb5TlWCE3 zb&e_4(@3&cW`q&Tm1R?0=6N=}$E7*HF7PpHtjF~YyP#Mx~W??^>|U z{NacN#Etzsj^BM#6xiusk9oQ42hO~F{;pbY$LD*OWU$-!tlSaC1@iC72)wk-^=1#D zVR<1a(ykO_o|xlz_=;W)p;-35fk5{12Oy!x4%+@;+FX3UQ;Kpl+_h1xQI}Rw(tFEn4 z5SvwZ1knpX?+G8~Xja*?J!H@J&Q*U1*^u~xlU=BoLd7UnPP}JCaRFTeR?(1c@IMqS zC7+Ru>7S`B7CN$zq7TKWrKBzoAlXLebSOrZq~m4ZTa!g3MlaT4o(Sgl9J z5FxqmS7YQ=S=Mu2X!OUhhon9j|5%NTcw4xYRowd9(p+((`&3fmy+9dBx1*S);(rms z8)`x4GVU+()rl$OqWfeJQ?l!z?Fk4@1PF$_x!29V?Vvy;`n04$lwf?An#X5N<-9)y zMa*Bfhm0Xmg!)$ryflq=(?0oyTd1=#^14_YUHA6-;Amc`A*Vbz5NHc^*Y|&G#}i=~ zs<^K{wuN;nFSJ!p+M(6I8brc8kjb32oUW$f9*zJ>;B zs+NAunGO9=Z=7@U@|~yxf!Z^UtTT>Z`W_`LqiwT$9i~l?=U_YT(A9vPoWk5 z9U~I8l(Z5Yf&K}tYQcN;{ynatTx$lRN4H}A441gJVK z3O>I_uyvo#e>+c(JNl%`txqEE6(3r5|7&$1gpwa&4?{)n1_qwwka~bC-kXAf?VD`0c zAjQc{->zfkwfNlMMcDuTvB;cFN8GT}P-8_6pRv7f`gWcy{sqWBnIWd27EqGfaN9)ZPeeD`t(}eS1fQzwEBs zeS14>yjUW8TojO{GM;Ju3LEpdPnnOJv%<&V07iMII(@KDX*V`uF0{lG6P5Lo)SqUK ztfw6|o&4KALX_Sngd8fgbEgO?@0luCIqtuqp7AsHD?8cvKWDdb25%A zves29prZRU?&^>aWMX?_ANtPPfs1|yl%EI5Nb*GZn47aJb?N7?Cz>zPgo~K#fA{{UU*6oz+E~QVlUSGOAIQPR!NA1H z&CNl~%F3Cv#n%tc#>ADB&rbw!u`vI4(00Vz$5(B+^{YNXRjiUvR=A&El4y(N+!vwGV2V;#xUxTI=V=8EHIqa{@ zzsvef*Av7aBq5hC_Ku2%U#AqeghJ0m)qOwoHE(ujLoB7)VkFmuxj4K%pYDGfYkXb2 zU+Zb~xx)_!V8yyJ{)8d^RHLI96e^^=NOg6H8VA;=!Nv$d8N5rU?Q5aTlL_zadr)Mj zU7Y~D-GKvuDyL~!ehQWN3q&%cY`=sNw*}-3D)+Jfv|PDd(pS|N&4EIJXw%G>(KA?k zxFf(ykhOiZ@0Gm>=v!<3${I8ARUXBE1{27cyQB5Q%LPZ=&XkJr;)0Y{>)IpF4p{A# z252VW_c5S6@nZ+8ZXY=3oNt+8``^B+RudA3@6qgGGm!WYl58T@BhK#0V+U@XvUryz zT&lej-HY-!IioAYyFU%Wwqx1u2Ct1xF5L+{(Y#0R3=@QMjvrUG+Xv&7JbR%stl%4TuKLiX{wxf$D8)?k?>NeBpmEG8N|DfV_pfK12mGEm9hTKL;ae0SGa@ zm5$_ngrR*2Pdnn;Ic=WG)h*`6uBxV@AL^P04ZD9{-0urp*q7B^mw$0L(K2MQ-!I@S zPL^RvmSSQYpBx>_eX|S;JTsU$l9O-PsK#uPM)&+ypfq1!qjBJhPW_v(7O`y=1B0gJ zY>Qnyq-D=4tF)OGS6#%Ry>><@1lV9Nk)L;|u*v)Bu&7q3=Z{j7nXfiRJzt_G1gVOm z(LBU%Y>th^-iq2?Ly522Jd5}&1CHquBLT-QLbA_PZL&hsqT}ZGWMq%G9xm#k>)zfu zsi6iV%E24p5!n3hbc1|6D-6E-$JP?j*+|;h#=5xWDo01u)Ye{}7(EgL1DIJ=8Df{f zQo|!_4f6Co`9Q?ww7}UbQpf@z_yMHCtGu3_}=_UD^&Ao4)gT#N=%c< zM1f=$rd96fNDXcpntJC3tf*kh-dssQJe$Jet^Agd1IbBzm?+6{Xw47}T~R2<+*+m; zZ9QE*(UO#~+`(_H*@6Z_L--3E>nh6W!)-3{zuC!b}%ZBM8Z<@RX1m_{<@AT&xy@ zOg8fQfniwg7OV)^HYik+?;z~5vEtT8V7}2X`oT(t5W!V6r$AMPE1jC&p%eHdSX-rt z^$19`auUvO^pe&pO6jrRSTGpcTgcPbf+mRPMTbp*BWds1t~Ex9b>mH3pk;(Nv8E=3xxhT3v+U_@N@ zx7J*cXyq?V*C#qka=t!Srp-+qV4o17JSrW}H4Gg?YIlr3O1!g(+di)_4a@+6K0{}U@@{q|KbgnumRJ6f>5cXB9 zF$B0J&Jc+kf-7t`ZNc|drQ(H*3R5kqhjP;;usu51&7T3Rxg45fo@EpoL0km<|ryb)DwQ7fIiUISynaE7wH# z61U}(JJg>Dx5yzk- z_A0Ku9K;AT-kdmBNwWKcnMlTVqkTP|yGwtDlg;p&F%{9~)H_vF$rEg3+0*x_Ae=y( z$OtsA*ft$817fwKy>a7-7*`=N=9my$%=&zp8WP_l5N@M&x-BgAMMjW4&TwrBnRo*w1q2pBB2bgCK z;P|A+SJGC|=3(8>)z$$yLy1gci%e3%q)E&Yu{fTx9wEs!K+vAgj)XXdt#TxIS*&@5 z#t&O{VOlV2l>Z&^WKZAk@ZpasKWOlEX#2?0?Z_HcPLHl^OI=vK8_L4INd5ct{OmDZ z<$xKDk>`MUo_}}5gptO8yemKP5-6ujN3K6T3TA?=0ns zr+Q9NJD~rF=vLiih*cSh^55|-3pY@H;608aC5F4h{$ms~)?ZU<!M%t~G>U6^UfW+kgh%!1Y`UrJc&Y4ouoxFO_3ah#JffnD zCxx)yaqy~Mh&A7rm&#R%qEB0dk4<%-GPD+%NLutm{!U7=e5NZ%=uH-lixqo7f+)Mq z_aB)^Xe!QdW5EBA^Hq390ptQFm#J|o4C0Iw9>Xn2Xcx&BhSM(-lQHAGdJ>JON<0*u zF=@29IF1*_)3=>-z)%x9(}Xt33)E%JUio~n_%XJ1Yko~s zy&8NlT$bTopYc8{hA`Uk{rS9WtC}?U+#1*P+ZoYyrZ$N3d)<;>1?sq;&Zs}^79@Sf zB}s$TBUE~fSQe9S?PPGL(%EQn*g_XGx|rj5$sBk#oD)X|%-KxPVxCd0RLH)KXD45A zX32d@6Qg5tHF{}l>^DrwY46(KrB7C;M@{=SXtTRou-<^;GEZN=B+O>w>-4R_5#lI z5OL>x@Uh+p*%v|EnWe>Ff!ERAqs2Q(M*`jlm*TdIkjScEE-sN4hFg8RyLdhZQ@Xxa z+c@*q+>rMhH%6v!-(s#@{=`DuFApZGDNAASU89qrH05$20UVx6kGnsiefT}cgSz;& zE`>*eBGiOnNxAFLQgh0GMw3ijFw$ojD15qsKDB-pd_o;xy`IfTGARPTqmt$Z>-eAM z7>R&aPR@nqC>;$Kj1u=z2hSUGm)Gu>1)}^L5`VwLd%_?^XJ7O))*9 z`Xd^E8#s1U9P`V#NrxbiNXB z=h*1k$#&7vn+YjCM3$9tt^V*^RUAWOgt%YXnhZ%;z^{)+rkMuCQ6Ka7*l2z%mT6xZ ze@Owdd!+F-#se^~hAE6mE^Udf=rZ#|1?3zB(}m00RDbJQmt<$3>yYOZ(}q zhHO)k>^kK2?E^T}r~A^3_NPRE(G+ILq1UKNNxJ_tWnoy^6n~N<(Azzgyd!o7Wl}+_ z+CjQ-C5Kq*qCv8J)yg@#$-oVk@Va)0{EU+W&e7?w)vKNkP6*mD*5UAGFWx2 z`)C@VxWn~Mq#Bt*$1T|R{i2g0%i7Owtg$rED^0y7_rUKVpa+*~s@-9vyL2h%>%nmr zIJ>}F&AjGZmlOH1+LfKsTHP5*i?w8*J?85K{bJPhO!-U#fl--g?ZTtFKnyv!z8(FV ze&}8jxHU%m*i827GbCkd*5zzYp?*M{cpUyGI*N7bZ{`$T08$|!LB>)_!Y_iB zAQg-D7o0iE9_-MK4BkSPL56~LSS{A}RYfqU;*0A!r4ZP+vi;Z{3RS00-`jiu@EDJk zaNUds3c^&gcpuM)LbE)$Z<8e4bH?rm{`%IhRN^QDY$fGxR-bxN;~Q-L`}(j!VNIc5>j2zvJ1q=~!D zCD6Z)aaQYg9S`MZ(eK0bRB{&MDhhXyD3ii8e!{EZnd0f6nh5UhVD#sLjDl+s z^-J}S$2E_oh^5kHI2{`K_z#HV&8JUpB{KfI3^h(NA`p|_^&b6+@q6YSc$rL?bkuSu zLd;j(*>dKO^P#itPS)@{^biL`ziP}+W;sjF`VPXN96LTdFnczrnf@l8tY7WhxbrBU zAPd)PiI?q)TE!~Q&6UhYW@7x%buPl#sK##Ir=}%r*e3xOG#a_Lwy|qsrliR5;yZFv zDUe=^ZTzH){GHIY%`*uPG|lvmn*8bhEY}h9>H9t>Ke0+&NK;6;?|{M?xkhQCG^|QW zh;kPnK!nVwlBt%?MHo+cH(mED-S@YMJa35iFQun)*~QaZjAn=?Jqy`X3PHxKr$30y znmSN7?%dgKWcN8!V?X}f`Mk6<5iw4VnZ7*x3J5T*L?4o2O-YWA0cbCtq9`9eoDK|F)yPob> z#qr#pq)16YgGvnlRYwG_J!^PZb<`HC%YWa17>CFj^w&Pa>WtShmQBP(e@pb@*EfOh z8m#0=;BxWDZ9EsI8dx_aEjKsvL#=FjZ|-d{JTVqjGsTyLD1gSAKt9aVY2WH2$_E6^ z_+nydd*9Wla=SbKAHCGio!2fcsTZkXu#fi7RYU%QosWko34zr*lvend_|)-}v)!3y zohu_G%eU`n9e%ZHW%Rf7FMQVOqTlL1%L_oV8kDUKp1Nnu2kN)#)UUNqstxwLM7aYCE$krPpmR9bZ<0VCI)-jPY zsO&Rq>g&*SiV+H)fi_wK&eDSfx6QQJJGba!s<>dMf(Evb-b=cQ#kyMu3!PrJ}_`bsTS83UvH7GnhIp zSY_e4xq5W152Bu4=nWvo-nA1Ujz8YFk72I!YIKHp;?xWLO`+uryMRIM0*gDQaiEpU zl|nTGy5q)SDUd5{>B=*)@V(T|UI!Jf5Az&8T z;BR2-YIYJLj(sTn5=+&))_rj_o7*9Doh72VuyGo}hE6 zN~}h26G6_TE6)>SSIT*RJ9G&Edgwj_3Ltob88@r~|BkvQM>j%=yWEoeo!dz`n0UAD z5DOLbLOz6Q^yI?kT^?1!X@62W9UK%1pfo0Axy?(e2Qld8g^h}jY@;$pn+j;?aa)AuH2?@^rxWlAybYy(rBAo@hm8=q5RvYnX4sC=C0-TQiHMgB#t{zE zvHy!2eDDk62Ae+f7LY#AI8s9He9Al2U!BGlg~k4LRce>ha;W|etVm9(c; zK4E%Qry}&F<}4QwGlyN6kmkQV`#_&9iJ-LedipOWri&CU`)9}rm|5d-!7IinQ6oiX=5)ioM0`~6~<6PqeR0w^GNjRVBpqNYn$foZH zIBo*bGd<5>r9c5RjTNEqxjiDrKn~I&BvJ7nRvK`m-H-YA-CClXH|D1zE3Y{($6JHz zT!M}PqU{_!HwPq#oAqAjx4&2W`ah1LF4_w271VB;d5dP~2k1AEdT$U$`{EY+@IDyY za@}@>O7digQmA{dPsMw&W*_z)eZJNv-JeXVvBD%3tAMt@iM&25OOUH#vVl11+oWlw zZRxTvm}t|oymzf5vVqQ(X$+O{26)r(3_PqTktu*y>qLjb{haaRxgNIi)r7zNR0=M&KA7{xbYnRfgKLh()^ek;f1xl1E1R zZ0OmNLBOYEa`w-pb1?c(RKuv?8BEQHrV!CcEo{VZMa_anCBI5Al?mK5cn)S_6b8vI$2CMB%gG;V==h{u8Y|4jsXDSaHc**RIPCVAAp=WIs0xrmf%=zIwHl1tE zgC-&UBnI?}**J-HIhdIkxLCQl*z}3n+5R;-I2gFOS(v&1$#Sx=Ffem)a&r>@Ka`t| zm4SK_n1hR0mz|x1ftj6!m5uoS>LLFBV*13K9K@X5#4Mcnod4!!VPYlbVj|Y% z;^O`{6%+G6wOq`^T&zhtI&?|#I-&pzH|Kw6>+};gY=W7PLvQZUT|0WT_^LbU!|N{_ zcg2yG{(`dM*yoQTAA~sWn3>SCA@5}kg?E1(2F@*>?7)&mY_nNSTo}n3<=Yu z788@V;mxPT)mS9hI;^bkYgPH1n8PCXbY0p_!-Ykq^Y|LgR{~XOCHrBld@fe`m=^3W0fc>`{eC=N&VVw`0`ayX6Ba)kVjiN zkp-w- z0v#~jh$0k7(z#BA{aI06#BYF9c>AXoJfyzmQTF^;$dWPUEZ0t#S|5BfvoGe`b&E^r0ttYyAW7#Y7 zO|c~<>qI|9X_&&GsR*hC46;~hfEj{>xd@Dz&^QDtOt=|23Zxzk7;cc1+q`}-WNjk@ zu}GLDa>Da(@c>!hnhTd75p{m$Fc+q)kSra`mXss|W7j`!^4|QO+&a4y)N^>;D}nQD z)iPEH7!t4wD!K>=Fja>h*QYh%@Q%nI=f#P3H-73_x-g*7D?_f=)#1o!utpyS)s{2b zDpcF=Z-tXuJHjxFOq?t?GZ+|Q^ubOU!B$8!Rpl|r(DP^}c9Q=0-666kwb*wvlp?64 z!4EaHwUy=394ryt(W!{r)S~^C${c5$V9A!=3Nc)M!H{nE24M$aj`)O+lYp+dq`~FS9K*!D z%{(cQ2LhKs_kwGm36kGt>YBRtBwatbrT35x(!0GbQKPCFh#L* zc5HI-lxjGk7Ks)?D8ghSzlf<95Q0X*Ak&2*i?VPEWtF-{5-`=&Xa@Eh1AWUj2yipG zm8FyaP)Eq+lVVImh|7vc-m5Q9@HB8YwcPDtvStwcO{XdO6}d5q-U_zC(Fhq6gG7TF z$D;L16N>R|EdU^^Q(-B22OBApq0ijhQk-vL5Z+syPF#CN9N3e>61a(}2sdRrJ9Z3* zqnUz$q)h8r-bcu8w981iw=Da8{*+TD4Y04Xm_Zy3bSJ$`s^xOz<6ZXiH z>sY81`@c_qx1y`cu4*5gk;(qyI>J(>n;?3+7Z0duV5kgzqi1X1k`5vhGc}jdR*q0p z#uzKX(xZ}~aUC5t0-@=2%h4L;T1RHdL?MAfjvtL1C@Yj--LsbnQmw{q zKNt%)-zC@IEDvSTqAULucVF>nAmYWIO^NOyy;!cE%vvya_N~Lz+=?>DjCq^6b*@5! z{t_VFV+nyE7(EFViBz#aQwlPmOR6l6SEHwKsh1Yh*;^W3Rz8{@<UD2Gei2ZOZ{P$sc~nJl7H__r`pWM>%EZls4%^ zMJFB_i!7#Wa7&Y~EPrMo6B5}di0Z5>%N?0TnyXbus?iqeC{xIfM#lc(jWY?=P^`cg zpL@;5Bt|d07zE8&92|B!){?|&Cc|+p<)+t*CjH^;8ooH<^oTAg%c?9-iRY8 zCG~S<35#DzPTi+Fo(14D34?KEH7uJ&It090^jt7^$BbzwIeFujuZaAg1rlTojriQAp={89ot@7-P zd>XsO#i$!W4l(OLems542eW~g`VP1rB%{CeUfZ!5D)D0sikHm4Pbd{0r}L=Ii-0sq zv+u}#ZC54p3DsF1tU{jN=S=Qgcq7!+VG|joJn+cX{Yd|z1#Lj$?KjBoeB*bsJRmp) zR8X(r&z0`GgVcR{TsXS;c$I$@#Bmt04cSYax72f_iO`4j`5ziRyWk9+ZVb{(h4B@keeWdthoV%8O67d68xp{N+dL)iHDGqT~%dnLZ zH#i*16ciQD?;A;BYBgjG^Hw1C!5TYiJ(JX&DK#a`V9m#F$93$9P;h*$AF)iaMVz%L zPeL%tqQ?(+<|q77mQwFYrf(`ME{vtp5!#AZk1rFej&<;|i3QYaVh!eK5J7kSj~(U~ zaMuT4x95tsU3sa2iyBTvNxyldC6s0{#vz(1rpL9Qkb{WWRh;PH9d1BWlH(xf>h6I_ zqI0WsfWf6iPb-Dl>ZQ8Tl^2VTrPg?ad%1F8W|lhw2*j3#!y(_O#zmV)mL%#?!dtM_ z_OTDY5`8D!zkNy$=aB_hOKR`YXodglRg?WNTi5&g3KkC-a5a8bSQ37m{k6x-NGseZ zL>e+l2mjF@cxpN?&jcV;&odU472b#mhN$6BWAeqoo@#^NjdLiBF-f4!I#){+frGh| z@NF6244>S-`K}A7BSs;m+#Yq(`#N;a?zcJyc+IEntymiUrgWH+>=NwQUn`Ei!p^jT z%)MU<$N5gxphGXo)f0QrHnm&7ibFhCVE%-!qf$FNv+sAAq6run-*EZ-JwLFVt!%vQ z{-r2E&@wD%F;0d$H;GWS=YFcMP-b3(iKa@(l3~TAgFy>X<1_(RqhZx3vIfVkG2S{T zr*qvI_1xocNO+}*2*DUTmYEg?47qGpXQlL)LDxt`8I1}#3;}M{p69F4Uw#&1V+ekE z#?Ux>N;Wih5r9Ue^7IFN%i-rKlV_6=u1;g;y{kX9cN0w8o0$f9?v5d>Cd3(LvTkO%#$~oSKVk=dLbSwN#u#tWiZ_Vx5E~zf+5xCTT?9HB{0zoUZLlLm~OeI&JBD!1m7%6LDa90&BYHgG?Py{TV0v3p*cFs9ab zB;&4+Gy!o=aijpK#9B7aa$2gn@kH$v>Z07yuOn>+8XrgMtc9!N{zCSG!J4%$>WZ z3fI<5lFQC(c>X@avKQ}bj7t!B=~<(x6R_*3CDJ3I*iQX%9vaK+xZ+i0qIyx+%+@ur z_d?mAjL*-OM+k+WAG?F?j<>h^>H$Fk9R!1b6!L9rg*f5)bbsTt z&;>Z#LF6xjqV>d_ig;1I{GW(2CQJFVRqm>)%*#dgs?0Aj@xf!ruT?uMwZ^fv(dW`6 z^fs!c!CqC6=h7ma4JkoCEByXGSZ=pywN(U!5I(x-G~sHKK3PA=__+OrEqw-as+mtc z)zLy^dHbB0<(;{!`t-!5Be=<@u-O0oN)OD87966io0ER1l$asTQk50jH_06r9}Y&8 z##{GBV8{`-xEUngBV)vu%D7T+2!o+nCawwi4gXP+7le5XD)c`M^v^$ed)(9V^ZH&L zFo8S1ny;QTr)R~!%q);yaYR!cOO8a#%HO=e|KotnCF*kgbNBwA@tHeMZOw1UHQ4Jeg?i7 z61Le)bnEif|4rE$+S9N z?_G#Qj~XO;XOthAQ3nYlTC^aD-iaKlJd!yDci!DB-Iab@8&%my%|y`5pfBYdGh@HmyLNF{uK) zR)+K)yf!oRC0sZsv=6SI8~Pb;)_nw3Ar*mx524rw#{Ny2p*B2;c7m|R>`>}}bjIop z7Fm^YMq_xbvPxLtS7j*$i#MWVgbr}qVL6F!_m4hl5IX3pl4C?elw>j)d*SP&a`lXw z>*iu_30}sg>u3{V3X}Lt(gDATz9#I~7qVwC+9;JJ)Pc89wvn$5XN zB+s{N3SK!-I`>6>zMl*@Jmi1uzh;2`WiE*-p zsB6gG0O+%~E8nfXBq=6c%T|F{ptJlI)@nN&X zc9dFajzN`{eM5z2Wr7xIOh26F5hH*$*-~Ok_fmQ3`&5{1YCxhxPKLjAH{{|VJe-ik z*nec$hsd%<48c+_5=6ZnDMoD(``LXrSMH^#{BY}MlGKgCG?JnXFsh~lWtsJ{1nDC& zE|YxxW9%W&QLX}`u52o+Md}-fdW#X06`Q*6?dSS?AI=ttbh^x&@`xP_@A)!ap4EkD z5UVBOFgPJsYhTkUZZGl3%Pn{3=PF5k3^*MsaA0ck-Smj0JruaWgV&KJaZ!E3HHuX% z&`@o;>_{O4{jle9ptE0dNa?c{L?wsiycx-PH?a%ITaF{&RZ%=Nlwgm>yGIA2i8X0- zORB$Y+J0mAwT>)b^`p89viNbe9WgRHB=lzivhDa-g2|*|^t$)QXjV9C%_+|Y@3OcE z{`FnYK`j+q(0yayfOuj5R#ZMmPUbPy5P6r?og_}uEhRGY;73szD(J#vdD+NBtMJxO zBnM@HS(t{SDngmIb~uBdczPrQ_G|~SGm3}7?q2xTGfNcb)xEyJ%a>G+DZl+Ci_`~~ z{}^50?c8U06C#o~)%IR20Kg)?(9!|prS48g?xjHp8eacn9q$d*;o^s@bu8es^)avh zX0QFDQ)9Ob{K9pF?}~J+LKa3YtSh^!v>#}qC2n1ohQ< z7xqPAI}PrCb(=1d4iIUO7SCq~0pd5m3V(i0#XXlZh05GSC(uU?Tw5%#k8usX+XfVh z!@_E@_GqrTr|?FUCB6Z7A*!!SlR^hnEpG&eTJdwhKYVSs%Iu(N3ktahQA%+o2@`P^ z#E+x5&4hLZ{W+tz?F&*7DV4zAbYm97N7C2E-E(*}*cVYUKgT7Zac0xuxt=zUfjK9? zwgKtZyd8?=Is&OI>^}4+s50u^26j*Jq9|#J)C~`eu1F0M^knZY&j15X(TxE)o_ds7 z%V}fuPmE25Yc0A$hGD@&@3uBCC@I>AeGAqQBq{I7V9l8~ikPrDJyTS)1<<%EKh||D z)nx1gDmnu5%nMn73T$!|Tv^hR2pF9Y8(OA<;*f#uo)WY2MjK7_Q9Fr1OtJr=4ylg4 zQHs0@f62_9daC48m*R`{;1KWiKdp#{TAP8tJRJ`|n=a=MhKWXf6MYtg;-&j*?@)0& zaj*KoxrvKu{+FCYUx0}?fdG@_0_4@Nc5gD$)Jhe)4ln+b`EXy(NiHEr@y_(7!hmL5 zW_idWhz7*9qWRlQb{1X(*p6)|G}FZ!O|DRwaGp(}KnMh;PgY z7T-<6@Av(ah<^*+i;{AmNJrs2X6R<&Q!<}DV#8*wd}d5s3{qiqhX0Ac=NbMr2cnYz zZ?(wL2$T9@g4|3p%PRu z9IwGhP(a(I*tsWNjUUEAdBneb)^kLtHITAqI6Q)06x$%{r!Hys&2j&WFrTZijP#D9 zn*Bm+ob9Q!DZn1Qqu8}arSN;5JBjwY|DQl>At-lSbb!U;KJoYMJO?j~x8KcZXY5$- zyy8k3(m5+}#_>NpyhJYz zvJGo=<~YjEFbu8)!tv$l!Jg8CI3gs%*!8p$sY}dn|Enh83`J!6lVc$O?uU6^U2J-C z`f@ArdgxnU zsn|%W+AJhYvcS1GpagKOrE<6zdx@aZTay*v&)y)`zx<%CJ)ppYKh!KZvmJa!zY}W!`r`dmuf&#Lcg*q3XQnxt>?t{Hm62l|Cx|I+8BxpuxDQ zHGhQW>&G&!{E_aFcWEhR6Xc74a9?=IiOqe~GwTI!%HN=DBgwQHvqLW%5urLuJ|J~X z9W%C8+~>BcF=~La8_5QR3BH&`5bkR*C%0JN z?Z?Hid;i8QNj9q|6g*xH=j}zsSXQPX-5xQa#SlxWjeA>9n!=W%*r~&jFB=K30j(Iv zG%O!fhTQ5)i~U`T2&S4IzzT5&?0miOtxjXil}=xnur$o;DaUQfUU?+-_$)EsE9;~( zAO@;RdwN2?PU|yh=k?tDjiPB>#`83J({=M|zt63a6#7xo{Imkxp$2>$fv@|XhhH&3 z8r~xjij(HZC`Elsq$os});!{&^GgOt+#v!%2pHn$fb@hg16!oKYcH<>0f@8WX|39} zXZPzHe|y1hk$t;vh7n8r&-yA!!qabszS|`5hUjbMk&h^T*0FWcxDA_Glqr;oeEqJU z+$7LlA4zVd3b)59oRbDJF37IyBol4^20PEFB_=VHl&wbRCQgS=MtYE%TwRGC>6sn& z;M|nK5G&*sL$QP__hrL?WhlRWA{%0_+FdeW@Jr9J#)-abIDEvk`rU6uCkQzRzeL>4 zC&^r9yT(zXdxSRg`Z?#d)At6Z8xwHFm%{d$QAG1Mj?@A+nTDFnf(0t`dP^z!A;!Y;kmqUn z#c*ThsQEk$=`V65onZXxJP_^@)+rqs^e->3( z)x+Cpk@q%Bo{InyxEdL6^Ob z0wwx^PN*}n0WzSZC6`u>vq>1d|4KBZpqhF9HuEBW$+mg5{b?Vp`xV{1)uOB18Vu|mQa6O}wwPeqi{~K$-W&^v9k9RsoS>B^HPD@Im=FXsFd3AK*E*6j65uL#c97 zj%gMd8ly7S`?|Zj_M;0@UsmOnzb_NkZTQ8W?}si}oog($*z=gYJUdvO=reu&>gns( zqp!l;-m|I!R0HXHCLAQm{Q8Hhpq__L`QMXjN>x){R0!*k+aozc+E)4XC2Bz9qL5Yzw;6 z+I&lgt8AFw>?aIMQN<2R#b{12If|RY87GIO<~!rBsb)6F<~dq)7G4PiyP}*0NeESNwOSVz zr^nHKrFTr}S-M-6YB1qL=y3O5lLWLEW(oglC)$K=7}sI!Yx9{J4(4V*w45}W4BiI( zxq-6Um&M%HD@(K5I6s8_U;MELv*XF@v8Xl?V*PQ1nQE!cHt&7fu1YYJegg9i*1;RR z!8PV-eI7@|bzc))9;_l8RVpL=-2H)})Dq7Fd*UD!+}++5IU)g=*3&)j2*b)$H0qIq zbI4s{Re1P$94eP9880|aGhKTew5tr*V$P4O{F+%ijC6947r_y6s<>7Zc}gv_B_c_Y zq+{b_<8v5oqV_vFYkRjO9XJoB6{*OwJIYEkRr>Jt<_>#R+O%k1Q4yrdBdjFYfM8-g z*06ozu3&5ZIC;XtGeWV%;19dnR9l(Vlrv+QDbwCw(FQBcI0n(={r{j5Dlq=Pa7b>! z0_bi0|3B$Jx&jb`@rf`S{Zlbv<`?|`IE4Qt5}?fJCIc$8SRg6gzk&+4#ovDc7@%nX zK*&Quk$*uFgl=I2bWz~Xy8=RJmmmtjFE|0idbgJ=2292l-kwPc!{CE`m182xKnA-f zu%^c`5xB!N1IurI1-!!AjcN4WKoP=2?bDhna?8%J50gnesr$11RvbB>XY~%Fj{S`M zl7EMv8&)9_)*{c+kKI#xd(%`!QZ}Xz7NQ=Hd?)ffFV>9L(klYKbHK`4xE=uP->XvJ z&|Qrmw)^Q-fBz*3>En|k?+>m fZR7kuG{OJFJ|7glhm<4Y;};U-eZa=1pr!aX(2bIr 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 8a0b33d7779e215a6b7e018d54d27c6b14c66d7a..e21638ce35259fc55a40aecdc83a7b9c11d8f749 100644 GIT binary patch delta 20966 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 delta 18185 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

+|tz3O-X8wV5P|A!=bdU>lX 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 bT7#k45_r_jWR++qE(0TD11?onSARDE#+~Y} 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}