\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.