

\section{Implementation}
Most of the theory behind RS and the methodology it depends on have already been introduced.
The implementation of a RS will be described in the following.
All examples have been written in a programming language called Python.
There is also some SQL code and some UML- and EER-diagrams in order to visualize the concept.
As database \gls{sqlite3} has been used.

\subsection{Content based RS in-depth}
\label{sec:implementation-contentbased}
The general framework for a content-based RS is shown in figure~\ref{fig:framework-contentbasedrs}.
There are three main components a content-based RS consists of.
\begin{itemize}
    \item \textbf{Content Analyzer}\hfill\\
        Since all items the RS has to work with are potentially unstructured, a pre-process is necessary to filter relevant information.
        This will be mainly done by IR-techniques.
        The Content Analyzer aims to bring all items in a form which can be used by its successional components.
        \citep[p.~75-77]{lops:2011}
    \item \textbf{Profile Learner}\hfill\\
        When the items are in a suitable form, the Profile Learner can construct a user profile.
        In case of Rocchio's algorithm this includes to distinguish all relevant items from non-relevant.
        Based on all items and the user's preferences the Profile Learner can build a user profile.
        Rocchio's algorithm uses a vector representing the users attitude towards different attributes of an item.
        In case of Rocchio, the user profile is a vector representing his attitude towards the different attributes an item may have.
        \citep[p.~75-77]{lops:2011}
    \item \textbf{Filtering Component}\hfill\\
        For each user profile the Filtering Component can find items which may match the users preferences.
        Depending on the method implemented the result can be a binary or continuous relevance judgment.
        The continuous relevance judgement is a list of ranked items.
        \citep[p.~75-77]{lops:2011}
        The RS implemented for this thesis uses k-nearest-neighbours classification.
        kNN results in a list of ranked items where $k$ best-ranked items will be suggested to the user.
\end{itemize}


\begin{figure}[h]
    \center
    \includegraphics[scale=0.4,clip=true,trim=24px 0 15px 0]{inc/implementation/HighlevelContentBased}
    \caption{High level description of a content-based RS.\citep[p.~76]{lops:2011}}
    \label{fig:framework-contentbasedrs}
\end{figure}


\input{inc/implementation/contentanalyzer/contentanalyzer}
\FloatBarrier
\input{inc/implementation/profilelearner/profilelearner}
\FloatBarrier
\input{inc/implementation/filteringcomponent/filteringcomponent}
\FloatBarrier

\subsection{Recommender library}
"Recommender library" labels the whole programming code which has been written for this thesis to a build programming library capable of creating item recommendations based on Rocchio's algorithm as declared in the milestones (figure~\ref{fig:softwaremilestones}).
In short it will be called "recommender.lib".
Since the previous sections already solved the goals defined by the milestones up to the library, this section describes recommender.lib's usage.

Following tasks are managed by recommender.lib:
\begin{itemize}
    \item Adding and removing products which can be recommended
    \item Creating, updating and removing users
    \item Making recommendations based on a user profile
\end{itemize}

\paragraph{Initialize recommender.lib}
In order to use recommender.lib on has to connect it to a database.
All database-tables required by recommender.lib will be created automatically when needed.
As main component \textit{DatabaseManager} delegates all tasks to other classes and gives access to them.
\begin{lstlisting}[language=Python,caption={Startup of recommender.lib},label={lst:recommenderlib-startup}]
import recommender
databasepath = "./database/recommender.sqlite3"
manager = recommender.DatabaseManager(databasepath)
\end{lstlisting}

\paragraph{Insert products}
With \textit{DatabaseManager} one can retrieve \textit{ProductManager} who is responsible for inserting and deleting products.
Afterwards a product can be added.
A product is no more than a collection of terms which describe it.
A term can be added by \textit{Product.add\_term()} with an optional second parameter describing its frequency.
If the parameter is omitted, the term's frequency will be set to 1.
\textit{Product} as derived class of \textit{Document} has an image\_name as special tweak which is used to store the file path of an image which represents the product.
\begin{lstlisting}[language=Python,caption={Insertion of products},label={lst:recommenderlib-product-insertion}]
product_manager = manager.get_product_manager()
p = recommender.product.Product()
p.image_name = 'image_01.png'
p.add_term('white')
p.add_term('blouse', 1)
product_manager.add_document(p)
\end{lstlisting}

\paragraph{Get product vectors}
With products added one can easily get their vectors (for example their \textit{tf-idf}-vectors).
In order to do so, one calls \textit{ProductVectorManager.get\_tfidf\_vector()} with the corresponding document\_id.
\textit{ProductVectorManager} also offers methods for creating \textit{tf}-, \textit{df}- and \textit{idf}-vectors.
When new products have inserted afterwards one has to delete all cached items of the \textit{ProductVectorManager} by calling \textit{ProductVectorManager.flush()}.
\begin{lstlisting}[language=Python,caption={\textit{tf-idf} vector of a product},label={lst:recommenderlib-product-vector}]
pvm = manager.get_product_vector_manager()
tfidf_vector = pvm.get_tfidf_vector(1)
print(tfidf_vector.values)  # prints: (0.0, 0.0)
\end{lstlisting}

\paragraph{Add users}
As next step a user will be created with \textit{UserVectorManager}.
Any user requires a user name which identifies him.
Recommender.lib however gives any user a unique id.
Methods working on users either require a \textit{user\_name} or \textit{user\_id}.
When a user is freshly created his vector will consist of numeric null.
\begin{lstlisting}[language=Python,caption={Add user},label={lst:recommenderlib-user-add}]
uvm = manager.get_user_vector_manager()
user_name = 'test_user'
uvm.create_user(user_name)
user_id = uvm.get_user_id_for_name(user_name)
user_vector = uvm.get_user_vector_for_id(user_id)
print(user_vector.values)   # prints: (0.0, 0.0)
\end{lstlisting}

\paragraph{Execute Rocchio's algorithm}
At the time there are both products available and users created one can start collecting user feedback.
Assuming that the user gives positive feedback towards the currently single product available the following listing will execute it.
The product will be marked as relevant and Rocchio's algorithm applied.
\begin{lstlisting}[language=Python,caption={Execute Rocchio's algorithm},label={lst:recommenderlib-rocchio}]
product_id = 1
uvm.set_user_preference(user_id, product_id, True)

relevant = uvm.get_relevant_document_vector_list(user_id)
non_relevant = uvm.get_non_relevant_document_vector_list(user_id)

updated_user_vector = recommender.rocchio.calculate(user_vector, relevant, non_relevant)
uvm.update_user_vector(user_id, updated_user_vector)
\end{lstlisting}

\paragraph{Finding recommendations}
Finally one can search for products which are similar to the user's vector.
This can be done by using \textit{k-nearest-neighbours} on the list of products and a user.
As a result a list with $k$ entries will be returned.
This list represents all recommendations.
Since kNN requires a distance-function for finding the nearest neighbours one can pass either a custom one, or use one of the pre-defined ones.
Currently supported are euclidean and hamming distance.
Because this kNN-implementation returns a combination of the distance and product-vectors, the vectors may have to be extracted.
\begin{lstlisting}[language=Python,caption={Retrieving recommendations},label={lst:recommenderlib-knn}]
distance_function = recommender.vector.arithmetic.euclidean_distance
k = 3
list_of_products = pvm.get_all_vectors()
meta_recommendations = recommender.vector.arithmetic.k_nearest_neighbours(
    k,
    updated_user_vector,
    list_of_products,
    distance_function
)
recommendations = [ vector for (distance, vector) in meta_recommendations ]
\end{lstlisting}

%Umfang und Aufgaben der Lib erkl\"aren.
\subsection{Web-API}
In order to operate the library from different programming languages except from Python a \gls{web api} has been implemented.
This API offers the most frequently function-calls a program using recommender.lib will require.
The online-shop introduced in section~\ref{sec:online-shop} has been written in \gls{javascript} calling the \gls{web api}.
Any request received by the web api through \gls{http} will result in a result containing a \gls{json} document.
An exhaustive list of all functions offered by the \gls{web api} and their return value is available in the appendix~\ref{sec:web-api}.

\input{inc/implementation/onlineshop/onlineshop}
\FloatBarrier

