3d-interface-rapport/rapport/architecture.tex

322 lines
12 KiB
TeX

\part{Architecture du programme}
Comme dit précédemment, le programme se décompose en un côté serveur et un côté
client. Le cas du \emph{streaming} sera traité à part (dans la partie
\ref{streaming}, puisqu'il est comporte des parties à la fois sur le client et
le serveur) et nous ne parlerons ici que du serveur, puis du code client.
\paragraph{}
Voici une \emph{simplification} de l'arborescence de la version de
développement :
\begin{figure}[H]
\centering
\begin{subfigure}[b]{0.3\textwidth}
\centering
\tikzstyle{every node}=[draw=black,thick,anchor=west]
\tikzstyle{folder}=[draw=blue, fill=blue!30]
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.7) and
two children at (0.5,-0.7) and (0.5,-1.4)},
edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node [folder] {root}
child { node [folder] {js}
child {node [folder] {l3d}
child {node [folder] {src}}
child {node [folder] {apps}}
}
child [missing] {}
child [missing] {}
child {node [folder] {Autres libraries}}
child {node {Makefile}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [folder] {lib}
child {node {NodeLog.js}}
child {node {controllers.js}}
child {node {posts.js}}
child {node {mail.js}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [folder] {controllers}}
child { node [folder] {posts}}
child { node [folder] {geo}
child {node {Geo.js}}
child {node {Mesh.js}}
child {node {MeshContainer.js}}
child {node {MeshStreamer.js}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node {private.js }}
child { node {package.json }}
child { node {npm-shrinkwrap.json }}
child { node {server.js }};
\end{tikzpicture}
\caption{Vue globale}
\end{subfigure}
~
\begin{subfigure}[b]{0.3\textwidth}
\centering
\tikzstyle{every node}=[draw=black,thick,anchor=west]
\tikzstyle{folder}=[draw=blue, fill=blue!30]
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.7) and
two children at (0.5,-0.7) and (0.5,-1.4)},
edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node [folder] {src}
child { node [folder] {cameras}
child { node {FixedCamera.js}}
child { node {PointerCamera.js}}
child { node {ReplayCamera.js}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [folder] {canvases}
child { node { MousePointer.js}}
child { node { Previewer.js}}
child { node { StartCanvas.js}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [folder] {loaders}
child { node { ProgressiveLoader.js }}
}
child [missing] {}
child { node [folder] {math}
child { node { Hermite.js }}
}
child [missing] {}
child { node [folder] {recommendations}
child { node { Arrow.js}}
child { node { Viewport.js}}
}
child [missing] {}
child [missing] {}
child { node [folder] {scenes}}
child { node [folder] {utils}
child { node [folder] {closure-compiler}}
child { node [folder] {simple-compiler}}
child { node { build\_all.sh}}
child { node { demon.sh}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child { node {l3d.js}}
;
\end{tikzpicture}
\caption{Détail des sources de L3D}
\end{subfigure}
~
\begin{subfigure}[b]{0.3\textwidth}
\centering
\tikzstyle{every node}=[draw=black,thick,anchor=west]
\tikzstyle{folder}=[draw=blue, fill=blue!30]
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.7) and
two children at (0.5,-0.7) and (0.5,-1.4)},
edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node [folder] {apps}
child {node [folder] {prototype}
child {node [folder] {interactive}
child {node {main.js}}
}
child [missing] {}
child {node [folder] {replay}
child {node {main.js}}
}
child [missing] {}
child {node [folder] {tutorial}
child {node {main.js}}
}
child [missing] {}
child {node [folder] {coin-creator}
child {node {main.js}}
}
child [missing] {}
child {node [folder] {coin-viewer}
child {node {main.js}}
}
child [missing] {}
child {node [folder] {coin-checker}
child {node {main.js}}
}
child [missing] {}
child {node {ButtonManager.js}}
child {node {Coin.js}}
child {node {GlobalFunctions.js}}
}
;
\end{tikzpicture}
\caption{Détail des applications}
\end{subfigure}
\caption{Arborescence du \emph{repository} de développement}
\end{figure}
\tikzstyle{every node}=[]
\section{Code serveur}
Le code serveur est situé à la racine du projet : le fichier \texttt{server.js}
est en fait le programme principal du serveur.
\subsection{Dépendances}
Le programme principal utilise de nombreuses libraires : les dépendances de
notre serveur sont définies dans le fichier \texttt{package.json}.
L'inconvénient d'avoir de nombreuses librairies en même temps est la
compatibilité des versions : en effet, une des dépendances nécessite une
version particulière d'une autre librairie. Chaque dépendance est une
librairie, qui a elle même ses dépendances, etc...
\paragraph{}
Nous avons eu ce problème au cours de notre projet : une librairie utilisait
une version précise d'une dépendance qui en nécessitait une autre. Nous avons
donc utilisé une fonctionnalité de \emph{npm} (le programme qui permet
d'installer des librairies dans un serveur NodeJs) qui s'appelle
\emph{shrinkwrap} et qui permet de figer l'arbre de dépendance d'une
application NodeJs.
\paragraph{}
Les \emph{packages} que nous utilisons sont les suivants :
\begin{itemize}
\item \emph{express} : un framework web pour NodeJs qui permet de gérer
facilement les urls, les requêtes, les réponses, etc...
\item \emph{jade} : un moteur de template pour simplifier la génération des
pages HTML
\item \emph{pg} : une librairie permettant la connexion à la base de données
\item \emph{body-parser} : une librairie permettant de traiter simplement
les paramètres passés aux requêtes
\item \emph{cookie-parser} et \emph{cookie-session} : une librairie gérant
les sessions sous forme de cookies
\item \emph{socket.io} : une librairie permettant d'utiliser facilement les
sockets (côté serveur et client)
\item \emph{serve-favicon} : une librairie pour choisir facilement l'icône
du site
\item \emph{emailjs} : une librairie permettant de se connecter à une
adresse e-mail
\end{itemize}
\subsection{Modèle, vue, contrôleur}
Pour ce projet, nous avons adopté une version simplifiée du design-pattern
\emph{modèle-vue-controleur} : en JavaScript, nos modèles seront des objets
simples (en JavaScript, un objet n'est qu'une liste de paire
\emph{clé-valeur}), et le modèle sera limité à l'exécution des requêtes SQL.
\paragraph{}
Les contrôleurs sont chargés au démarrage par le fichier
\texttt{controllers.js}, qui parcourt les dossiers qui sont contenus dans le
dossier \texttt{controllers}. Dans chacun de ces dossiers, deux fichiers et un
dossier sont présents :
\begin{itemize}
\item \texttt{index.js} qui contient des fonctions (contrôleurs) qui
répondent à des requêtes
\item \texttt{urls.js} qui contient les urls existantes et les fonctions
auxquelles elles vont être associées
\item \texttt{views}, dossier qui contient les vues qui vont être utilisées
par les contrôleurs définis dans \texttt{index.js}
\end{itemize}
\paragraph{}
La même technique à été appliquée pour le dossier \texttt{posts} et le fichier
\texttt{posts.js}, à la différence près que les requêtes traitées sont des
requêtes POST et non pas des requêtes GET : elles servent principalement à
stocker des informations dans la base de donneés.
\newpage
\section{Code client}
Le code client est séparé en trois parties :
\begin{itemize}
\item une partie dans le répertoire \texttt{src} contenant de nombreuses
fonctions et classes
\item une partie dans le répertoire \texttt{apps} contenant des
applications que nous avons développées
\item des autres librairies développées par des tiers, dans le répertoire
\texttt{js}
\end{itemize}
Le \texttt{Makefile} présent dans le dossier \texttt{js} est celui qui
concatènera nos sources, les \emph{minifieras} et génèrera les scripts que nous
utiliserons par la suite.
\paragraph{}
Dans la suite, nous allons seulement parler de L3D, puisque c'est le code que
nous avons développé.
\subsection{Les sources}
L3D est composée de plusieurs classes :
\begin{itemize}
\item les caméras, permettant de choisir des caméras avec des mouvements
particuliers
\item les canvas, qui permettent d'afficher des informations
supplémentaires à l'écran
\item les loaders, qui permettent de charger des modèles de manière
différente de celles proposées par \threejs{}
\item les classes mathématiques, comme les polynômes de Hermite
\item les recommandations, notamment les flèches et les \emph{viewports}
\end{itemize}
\paragraph{}
Elle contient aussi quelques fonctions qui permettent de créer les scènes que
nous avons utilisées, et notamment leurs recommandations et leurs pièces
rouges.
\paragraph{}
Dans le répertoire \texttt{utils}, il y a plusieurs outils pratiques pour le
développement et le déploiement : c'est là qu'est rangé le \emph{minifier} de
Google, \closurecompiler{}, et une version simplifiée, le Simple-Compiler, qui
utilise les mêmes paramètres mais se contente de concaténer le code.
\paragraph{}
Pour L3D, le premier fichier qui sera dans la version finale est
\texttt{l3d.js}. Il contient simplement l'initialisation du \emph{namespace}
\texttt{L3D}, auquel toutes les classes et fonctions appartiendront.
\subsection{Les applications}
Les applications sont principalement composées de programmes principaux, qui
utilisent les classes de L3D, ainsi, elles ne sont pas fusionnées avec L3D, et
laissées dans le namespace global.
\subsubsection{Interactive}
Ceci est l'interface principale, où l'utilisateur doit rechercher les pièces.
Nous en parlerons plus dans la section \ref{interface}.
\subsubsection{Replay}
C'est l'interface qui crée une \texttt{ReplayCamera} et permet de visionner une
expérience qui a été faite dans le passé.
\subsubsection{Tutorial}
C'est le tutoriel de l'application : il possède notamment une classe qui copie
la caméra principale tout en permettant de vérifier que les interactions sont
faites comme il faut.
\subsubsection{Coin-creator}
C'est une interface qui permet de créer des pièces : en cliquant sur une paroi,
une pièce apparaît, et en cliquant sur une pièce, elle disparaît. Cette
interface possède un bouton qui permet d'envoyer un mail contenant les données
des pièces créées au format JSON.
\subsubsection{Coin-editor}
Cette interface permet d'éditer les pièces : elle est similaire à la
précédente, mais expose une variable globale lors du clic sur une pièce qui
permet de déplacer celle-ci. Elle sert à corriger les bugs potentiels
introduits par l'interface précédente, notamment lorsqu'une pièce traverse une
paroi.
\subsubsection{Coin-checker}
Elle permet de chercher toutes les pièces d'une scène, au cas où certaines se
soient glissées à l'intérieur du modèle. Elle contient notamment un affichage
du nombre de pièces présentes sur la scène, et cliquer sur une pièce la
supprime.