Add entire report
This commit is contained in:
parent
68e793689c
commit
e4979378b4
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
rapport.pdf
|
BIN
Firework.pdf
Normal file
BIN
Firework.pdf
Normal file
Binary file not shown.
BIN
Fractal.pdf
Normal file
BIN
Fractal.pdf
Normal file
Binary file not shown.
@ -1,2 +1,9 @@
|
||||
# AC20
|
||||
|
||||
This project is about creating demos for the SARL language.
|
||||
|
||||
You can compile the report with pandoc with the command
|
||||
|
||||
```shell
|
||||
pandoc --template=default.latex rapport.md -o rapport.pdf
|
||||
```
|
||||
|
201
ac20.cls
Normal file
201
ac20.cls
Normal file
@ -0,0 +1,201 @@
|
||||
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
|
||||
\ProvidesClass{ge11}[2017/06/13 v1 Mise en forme AC20]
|
||||
|
||||
% Passe les options de la classe à la classe article
|
||||
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
|
||||
\ProcessOptions
|
||||
|
||||
\LoadClass[titlepage, a4paper, french,]{article}
|
||||
|
||||
\usepackage[right=2.3cm,left=2.3cm]{geometry}
|
||||
\usepackage{pifont}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{lmodern}
|
||||
\usepackage{amssymb,amsmath}
|
||||
\usepackage{ifxetex,ifluatex}
|
||||
\usepackage{fixltx2e} % provides \textsubscript
|
||||
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage{eurosym}
|
||||
\else % if luatex or xelatex
|
||||
\ifxetex
|
||||
\usepackage{mathspec}
|
||||
\else
|
||||
\usepackage{fontspec}
|
||||
\fi
|
||||
\defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}
|
||||
\newcommand{\euro}{€}
|
||||
\fi
|
||||
|
||||
% use upquote if available, for straight quotes in verbatim environments
|
||||
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
|
||||
% use microtype if available
|
||||
\IfFileExists{microtype.sty}{%
|
||||
\usepackage[]{microtype}
|
||||
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
|
||||
}{}
|
||||
\PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref
|
||||
\usepackage[unicode=true]{hyperref}
|
||||
\hypersetup{
|
||||
pdftitle={La programmation orientée agent},
|
||||
pdfauthor={Bartuccio Antoine},
|
||||
pdfborder={0 0 0},
|
||||
breaklinks=true}
|
||||
\urlstyle{same} % don't use monospace font for urls
|
||||
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
|
||||
\usepackage[shorthands=off,main=french]{babel}
|
||||
\else
|
||||
\usepackage{polyglossia}
|
||||
\setmainlanguage[]{french}
|
||||
\fi
|
||||
\usepackage{color}
|
||||
\usepackage{fancyvrb}
|
||||
\newcommand{\VerbBar}{|}
|
||||
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
|
||||
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
|
||||
% Add ',fontsize=\small' for more characters per line
|
||||
\newenvironment{Shaded}{}{}
|
||||
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
|
||||
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}}
|
||||
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
|
||||
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
|
||||
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
|
||||
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}}
|
||||
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
|
||||
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
|
||||
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
|
||||
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
|
||||
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}}
|
||||
\newcommand{\ImportTok}[1]{#1}
|
||||
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}
|
||||
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}}
|
||||
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
|
||||
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
|
||||
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
|
||||
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}
|
||||
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}
|
||||
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
|
||||
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
|
||||
\newcommand{\BuiltInTok}[1]{#1}
|
||||
\newcommand{\ExtensionTok}[1]{#1}
|
||||
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}}
|
||||
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}
|
||||
\newcommand{\RegionMarkerTok}[1]{#1}
|
||||
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
|
||||
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
|
||||
\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
|
||||
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
|
||||
\newcommand{\NormalTok}[1]{#1}
|
||||
\usepackage{graphicx,grffile}
|
||||
\makeatletter
|
||||
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
|
||||
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
|
||||
\makeatother
|
||||
% Scale images if necessary, so that they will not overflow the page
|
||||
% margins by default, and it is still possible to overwrite the defaults
|
||||
% using explicit options in \includegraphics[width, height, ...]{}
|
||||
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
|
||||
\IfFileExists{parskip.sty}{%
|
||||
\usepackage{parskip}
|
||||
}{% else
|
||||
\setlength{\parindent}{0pt}
|
||||
\setlength{\parskip}{6pt plus 2pt minus 1pt}
|
||||
}
|
||||
\setlength{\emergencystretch}{3em} % prevent overfull lines
|
||||
\providecommand{\tightlist}{%
|
||||
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
% Redefines (sub)paragraphs to behave more like sections
|
||||
\ifx\paragraph\undefined\else
|
||||
\let\oldparagraph\paragraph
|
||||
\renewcommand{\paragraph}[1]{\oldparagraph{#1}\mbox{}}
|
||||
\fi
|
||||
\ifx\subparagraph\undefined\else
|
||||
\let\oldsubparagraph\subparagraph
|
||||
\renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}}
|
||||
\fi
|
||||
|
||||
\usepackage{float}
|
||||
\floatplacement{figure}{!h}
|
||||
|
||||
% set default figure placement to htbp
|
||||
\makeatletter
|
||||
\def\fps@figure{htbp}
|
||||
|
||||
\newcommand\UV[1]{\newcommand\@UV{#1}}
|
||||
\newcommand\semester[1]{\newcommand\@semester{#1}}
|
||||
\newcommand\UVManager[1]{\newcommand\@UVManager{#1}}
|
||||
\newcommand\UVFollower[1]{\newcommand\@UVFollower{#1}}
|
||||
|
||||
% Entête et pied de page
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{lastpage}
|
||||
|
||||
\pagestyle{fancy}
|
||||
\fancyhead{}
|
||||
\fancyfoot{}
|
||||
|
||||
\fancyheadoffset{0cm}
|
||||
|
||||
\rfoot{
|
||||
\begin{minipage}{6cm}
|
||||
\includegraphics{utbm_logo.png}
|
||||
\end{minipage}
|
||||
}
|
||||
\lfoot{\thepage/\textbf{\pageref{LastPage}}}
|
||||
|
||||
\lhead{\bsc{\@author}}
|
||||
\rhead{\textit{\@title}}
|
||||
|
||||
\fancypagestyle{titlepage}{
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
\fancyfoot[R]{\includegraphics{utbm_logo.png}}
|
||||
\fancyfootoffset{-0.5cm}
|
||||
}
|
||||
|
||||
\newcommand\cover{
|
||||
\begin{titlepage}
|
||||
\thispagestyle{titlepage}
|
||||
|
||||
\begin{center}
|
||||
{\Huge\textbf{\@title}}
|
||||
|
||||
\hspace{20cm}
|
||||
|
||||
{\Large Réalisé dans le cadre de l'unité de valeur}
|
||||
\end{center}
|
||||
\begin{center}
|
||||
{\Large\textbf{\@UV}}
|
||||
|
||||
\vspace{10em}
|
||||
|
||||
{\Large Écrit par \textbf{\@author}}
|
||||
|
||||
{\Large\@date}
|
||||
|
||||
\vspace{10em}
|
||||
|
||||
Gestionnaire de l'UV : \@UVManager
|
||||
|
||||
Professeur encadrant : \@UVFollower
|
||||
\end{center}
|
||||
|
||||
\end{titlepage}
|
||||
}
|
||||
|
||||
\makeatother
|
||||
|
||||
% Puces modifiées
|
||||
\setlist[itemize]{label=\textbullet}
|
||||
|
||||
% Changement du titre de la table des matières
|
||||
\addto{\captionsfrench}{\renewcommand*{\contentsname}{Sommaire}}
|
||||
|
||||
\renewcommand\thesection{\arabic{section}}
|
||||
\renewcommand\thesubsection{\thesection.\arabic{subsection}}
|
||||
\renewcommand\thesubsubsection{\thesubsection.\arabic{subsubsection}}
|
||||
|
||||
% Saut de page automatique après chaque section
|
||||
\let\oldsection\section
|
||||
\renewcommand\section{\clearpage\oldsection}
|
28
default.latex
Normal file
28
default.latex
Normal file
@ -0,0 +1,28 @@
|
||||
\documentclass[11pt]{ac20}
|
||||
|
||||
\title{$title$}
|
||||
\author{$author$}
|
||||
|
||||
\date{$date$}
|
||||
\UV{$UV$}
|
||||
\UVManager{$UVManager$}
|
||||
\UVFollower{$UVFollower$}
|
||||
\semester{$semester$}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\cover
|
||||
\clearpage%
|
||||
\thispagestyle{empty}%
|
||||
\null%
|
||||
\clearpage
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
$body$
|
||||
|
||||
\newpage
|
||||
|
||||
\listoffigures
|
||||
|
||||
\end{document}
|
BIN
firework_screenshot.png
Normal file
BIN
firework_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 307 KiB |
324
rapport.md
Normal file
324
rapport.md
Normal file
@ -0,0 +1,324 @@
|
||||
---
|
||||
title: La programmation orientée Agent
|
||||
author: Bartuccio Antoine
|
||||
UV: AC20
|
||||
semester: TC04
|
||||
date: Printemps 2017
|
||||
UVManager: FLESCH Alexis
|
||||
UVFollower: GAUD Nicolas
|
||||
---
|
||||
|
||||
# Découvrir un nouveau paradigme
|
||||
|
||||
## Les paradigmes dans les langages de programmation
|
||||
|
||||
Il y a de nombreuses manières de penser un programme informatique et c'est pour cela qu'il existe de nombreux langages pour les écrire. Au delà de la différence de syntaxe, des idiomes et des philosophies différentes, autre chose change : le ou les paradigmes. Le *paradigme* correspond à la manière de formuler la solution à son problème dans un langage de programmation et influe grandement sur l'esprit du développeur lors de la conception de son algorithme.
|
||||
|
||||
Il existe de nombreux paradigme. Le plus simple (pour la machine) est la programmation impérative que l'on retrouve en assembleur ainsi qu'en C. On retrouve également la programmation orientée objet (POO) plus récente que la procédurale, très répandue et très appréciée. Il est tout à fait possible de mélanger différents paradigme dans le même langage de programmation comme par exemple en Python où il n'est pas choquant d'appeler des objets en plein milieu d'un programme pensé de manière procédurale.
|
||||
|
||||
Découvrir un nouveau paradigme permet de penser ses programmes différemment, de penser à de nouvelles méthodes de résolution d'un algorithme, penser plus loin que ce à quoi on est déjà habitué, de réfléchir à ses pratiques et de ce fait de les remettre en question.
|
||||
|
||||
## L'orienté agent
|
||||
|
||||
Ici, nous allons nous intéresser à la programmation orientée agent.
|
||||
|
||||
La programmation orientée agent (POA) se base sur le concept d'agent logiciel. L'POA est une abstraction de la POO offrant des agents capable d'agir indépendamment et d’échanger des messages entre eux pour interagir et atteindre leur objectif. L'agent tire parti du multitâche en créant automatiquement des sous-processus propre à chaque agent et crée des espaces de communication pouvant recevoir des événements normalisés.
|
||||
|
||||
## Le choix du SARL
|
||||
|
||||
Il est possible de faire de la POA avec un langage orienté objet classique. Cependant, cela nécessite un important travail d'abstraction et d'implémentation. Même après cela, utiliser l'agent n'est ni intuitif ni naturel pour le programmeur. C'est comme faire de l'objet dans un langage structuré comme le C, c'est possible mais pénible.
|
||||
|
||||
Il existe très peu de langages nativement orientés agent. Le choix était donc aisé puisqu'un langage développé par l'UTBM existe, il s'agit du SARL.
|
||||
|
||||
Le SARL est construit sur le Java. C'est un langage multi-paradigme puisqu'il supporte entre autres l'agent et l'objet. Le langage est construit autour de la bibliothèque Janus qui fourni les bases de l'POA en Java. De plus, puisque SARL est trans-pillé en Java, il peut faire appel à des objets écrits pour le Java, ce qui permet d'accéder à de très nombreuses librairies et de travailler efficacement.
|
||||
|
||||
En plus du paradigme différent, le SARL propose une architecture d'agent assez intéressante. Les agents sont holoniques, ils peuvent contenir leurs propre agents et leur propre espace de communication. En plus de cela, grâce à la plate-forme Janus, les agents peuvent être redistribués sur le réseau et être exécutés sur différentes machines.
|
||||
|
||||
## L'agent en SARL
|
||||
|
||||
En SARL, un agent peut, comme un simple objet, contenir des attributs et des méthodes. Cependant, celui-ci possède son propre processus et peut percevoir des événements grâce à ses perceptions. Ainsi, un agent peut réagir ou non à un événement donné selon les conditions (garde) choisi par le programmeur. Un agent peut réagir au même événement avec plusieurs perceptions différentes qui s'exécuteront simultanément.
|
||||
|
||||
Initialisation d'un agent simple pouvant recevoir un événement de renommage
|
||||
|
||||
```Scala
|
||||
agent MyAgent {
|
||||
var name : String
|
||||
|
||||
on Initalize {
|
||||
name = "Bob"
|
||||
}
|
||||
|
||||
on Rename [name !== null]{
|
||||
name = "Jean Charles"
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Un agent peut également obtenir des capacités étendant ses fonctionnalités. Un agent peut écrire dans les logs, émettre des événement dans l'espace où il est enregistré, détecter la présence d'autres agents, accéder à son espace interne…
|
||||
|
||||
Exemple d'utilisation de l'utilisation de la capacité *logging*
|
||||
|
||||
```Scala
|
||||
import io.sarl.core.Logging
|
||||
|
||||
agent Steeve {
|
||||
|
||||
uses logging
|
||||
|
||||
on Hack {
|
||||
println("Haked")
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Un agent peut, comme expliqué précédemment, posséder son propre contexte interne. À l’intérieur de ce contexte interne, il est possible d'instancier d'autres agents qui eux mêmes possèdent leur propre contexte interne. Cela permet une organisation holonique de son application.
|
||||
|
||||
Exemple d'agent qui crée (*spawn*) un nouvel agent dans son contexte interne :
|
||||
|
||||
```Scala
|
||||
import io.sarl.core.InnerContextAcess
|
||||
|
||||
agent Smith {
|
||||
uses InnerContextAccess
|
||||
|
||||
on CreateInnerAgent {
|
||||
spawnInContext(Smith, innerContext)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Les événements
|
||||
|
||||
Comme dit précédemment, les agents communiquent à l'aide d'événements. Les événements peuvent s'apparenter à des appels de méthodes en POO. Cependant, l'événement est bien plus puissant. Il peut, au travers de la plate-forme Janus, se propager sur le réseau et interagir avec les agents partagés.
|
||||
|
||||
```Scala
|
||||
/* Déclaration d'un événement simple */
|
||||
event MyEvent
|
||||
```
|
||||
|
||||
Un événement est également capable de transmettre des informations. Il est également possible pour l'agent de récupérer des informations sur l'émetteur de l'événement.
|
||||
|
||||
```Scala
|
||||
/* Événement possédant des propriétés */
|
||||
event CoolEvent {
|
||||
var name : String
|
||||
var nb : Integer
|
||||
|
||||
/* Constructeur de l'événement */
|
||||
new(_name : String, _nb : Integer) {
|
||||
name = _name
|
||||
nb = _nb
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Un événement atteint par défaut tous les agents présents sur l'espace d'émission. Il est également possible pour un agent de s'envoyer un événement à lui même (avec la méthode *wake* qui est très rapide) ou à un agent en particulier si son ID est connu.
|
||||
|
||||
```Scala
|
||||
agent EventSender {
|
||||
on Initialize {
|
||||
emit(new MyEvent)
|
||||
wake(new CoolEvent("Cool", 7))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Puisqu'un événement est envoyé sur un espace, il faut comprendre comment ceux-ci fonctionnent pour gérer efficacement les communications entre agents. Un espace est contenu dans un contexte. Un contexte peut contenir $n$ espaces. Chaque contexte contient un espace par défaut. Il existe un contexte par défaut généré lors de la création d'une application SARL. Il est possible de créer autant de contexte que l'on souhaite et un contexte peut être contenu dans un agent.
|
||||
|
||||
# Penser agent dans son application
|
||||
|
||||
## Une architecture adaptée
|
||||
|
||||
Des agents seuls, part nature, ne peuvent constituer une application complète. Cependant, il est possible de s'en servir comme d'un noyau applicatif sur lequel lire des informations et communiquer. L'interface utilisateur serait un simple objet qui communiquerai avec les agents.
|
||||
|
||||
Il existe plusieurs manières d'agencer son application pour parvenir à cela, celle retenu est la méthode Modèle-Vue-Contrôleur (MVC). L'idée est de séparer le Modèle (ici les agents) de la vue (GUI) ainsi que du Contrôleur qui ordonne le modèle et la vue.
|
||||
|
||||
![Le modèle MVC mis en place dans ce projet](MVC.pdf)
|
||||
|
||||
## Prise en main du langage
|
||||
|
||||
### Démo de feux d'artifices
|
||||
|
||||
Le but de cette démo est de faire apparaître des feux d'artifices à partir d'agents SARL. L'application est découpée en 4 agents distincts et le tout est construit sur une structure holonique.
|
||||
|
||||
![Organisation des agents pour la démo de feux d'artifices](Firework.pdf){ width=150px, height=300px }
|
||||
|
||||
L'agent principal est la *LaunchingArea* qui fait le lien entre la GUI et le reste des agents SARL. C'est elle qui va créer les *RocketLauncher*, un lanceur par roquette demandé par l'utilisateur, et leur transmettre la gravité et autres paramètres. Cet agent se charge aussi d'enregistrer la GUI sur un espace de communication dédié.
|
||||
|
||||
```Scala
|
||||
agent LaunchingArea {
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Réception de l'événement de configuration venant de la GUI
|
||||
*/
|
||||
on SetupSettings {
|
||||
this.rocketsQuantity = occurrence.rocketsQuantity
|
||||
this.fireQuantity = occurrence.fireQuatity
|
||||
this.gravity = occurrence.gravity
|
||||
this.maxWidth = occurrence.maxWidth
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialisation de l'agent lorsqu'il
|
||||
* est généré par la GUI
|
||||
* Un espace de communication est ouvert
|
||||
* entre la GUI et l'agent
|
||||
*/
|
||||
on Initialize [!occurrence.parameters.empty] {
|
||||
var ctrl = occurrence.parameters.get(0) as FXMLViewerController
|
||||
var ispace = defaultContext.createSpace(
|
||||
OpenEventSpaceSpecification, UUID.randomUUID)
|
||||
ctrl.setGUISpace(ispace)
|
||||
ispace.register(asEventListener)
|
||||
|
||||
ctrl.listenAndDraw(grid)
|
||||
|
||||
info("Finishing initialization of Launching Area")
|
||||
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
![Rendu de l'application sur la GUI](firework_screenshot.png){ width=350px, height=300px }
|
||||
|
||||
Viennent ensuite les RocketLauncher qui chacun font apparaître une *Rocket*. Dès que celle-ci est détruite, le *RocketLauncher* va en générer une nouvelle. Cela permet de déporter la logique de vérification d'existence des *Rocket* hors de la LaunchingArea et d'isoler les *Rocket*, et ainsi d'éviter que les événements émis par celles-ci ne viennent perturber leur fonctionnement.
|
||||
|
||||
```Scala
|
||||
agent RocketLauncher {
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Lancement d'une nouvelle roquette lorsque
|
||||
* la précédente est détruite
|
||||
*/
|
||||
on MemberLeft [!isFromMe(occurrence) && !exited] {
|
||||
// wake permet d'envoyer l'événement à l'agent lui même
|
||||
wake(new Launch)
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Les *Rocket* sont au cœur de la démo. Elles lancent chacune une tache à délais fixé où elles mettent à jour leur position et l'inscrivent dans l'objet partagé avec la GUI ici nommé *Positions*. Une fois leur durée de vie dépassée, elle génèrent dans leur contexte interne des *Fire* en accord avec la quantité demandé par l'utilisateur et attend leur destruction pour se détruire.
|
||||
|
||||
```Scala
|
||||
agent Rocket {
|
||||
|
||||
...
|
||||
|
||||
on Initialize {
|
||||
|
||||
...
|
||||
|
||||
/*
|
||||
* Crée une tâche de fond pour mettre à jour
|
||||
* sa position à délai fixé
|
||||
*/
|
||||
move = atFixedDelay(
|
||||
Configuration.RocketLifeCycleSchedulingRate) [
|
||||
try {
|
||||
wake(new UpdateRocketPosition);
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
on UpdateRocketPosition [isFromMe(occurrence) &&
|
||||
!frozen && !exploded] {
|
||||
var vect = new Vector(2)
|
||||
x = x + speedx
|
||||
y = y + speedy
|
||||
vect.clear()
|
||||
vect.add(x)
|
||||
vect.add(y)
|
||||
lifetime = lifetime - 10
|
||||
|
||||
/* Mise à jour de l'objet Position */
|
||||
if (grid !== null)
|
||||
grid.setRocketPosition(id, vect)
|
||||
if (lifetime <= 0) {
|
||||
exploded = true
|
||||
move.cancel(true)
|
||||
grid.hideHocketPosition(id)
|
||||
wake(new Explode)
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Les *Fire* sont les derniers maillons de cette démo. Ils possèdent une liste de positions et sont soumis à la gravité. Tout comme l'agent *Rocket*, le *Fire* lance une tâche à délai fixé pour mettre à jour sa position actuelle, la rajouter à la fin de sa liste de positions et rajouter cette liste dans l'objet *Positions*. Lorsque sa durée de vie est dépassée, le *Fire* se détruit.
|
||||
|
||||
Lorsque la GUI est fermée, un événement d'extinction *Exit* est envoyé à la *launchingArea* qui se charge de le transmettre aux agents qu'elle contient et attend leur destruction pour se détruire et ainsi de suite en descendant dans la hiérarchie.
|
||||
|
||||
\newpage
|
||||
|
||||
### Démo de fractales
|
||||
|
||||
|
||||
Cette démo présente des fractales de Sierpinski. Cela correspond à mettre 3 triangles dans un triangle.
|
||||
|
||||
![Organisation des agents pour la démo de fractales](Fractal.pdf){ width=150px, height=300px }
|
||||
|
||||
Pour réaliser cette démo, un seul agent est nécessaire. Le principe est que cet agent principal crée 3 autres agents dans son contexte interne et devient ensuite un simple transmetteur d'événement et ainsi de suite pour chacune des fractales nouvellement crées.
|
||||
|
||||
|
||||
```Scala
|
||||
agent Fractal {
|
||||
...
|
||||
|
||||
on Initialize {
|
||||
if (occurrence.parameters.size >= 2){
|
||||
// Si initialisé avec arguments
|
||||
|
||||
screenSurface = occurrence.parameters.get(0) as Square
|
||||
positions = occurrence.parameters.get(1) as Positions
|
||||
|
||||
if (occurrence.parameters.size.equals(3)){
|
||||
// Si initialisé par la GUI
|
||||
var ctrl = occurrence.parameters.get(2) as FXMLViewerController
|
||||
guiSpace = defaultContext.createSpace(
|
||||
OpenEventSpaceSpecification, UUID.randomUUID)
|
||||
ctrl.setGUISpace(guiSpace)
|
||||
guiSpace.register(asEventListener)
|
||||
}
|
||||
} else {
|
||||
// Si initialisé sans arguments
|
||||
screenSurface = new Square
|
||||
positions = new Positions
|
||||
}
|
||||
screenWidth = screenSurface.width
|
||||
this.generatePoints
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
![Rendu de l'application sur la GUI](sierpinski_screenshot.png){ width=250px, height=250px }
|
||||
|
||||
\newpage
|
||||
|
||||
## Difficultés rencontrées
|
||||
|
||||
Le fait que l'agent s'exécute dans un sous-processus change complètement la manière de penser son application. Lors de la réalisation de la démo de feux d'artifice, il a fallu synchroniser les départs de fusées et les départs de flammes lors de l'explosion. D'habitude, il aurait suffi de calculer les positions de tous les éléments puis de lancer l'affichage. Ici, puisque chaque agent est indépendant, on ne peut que lire les positions et donc les positions d'une roquette changent pendant qu'une autre roquette est générée. Il a donc fallu exploiter les capacités des agents et leur faculté à détecter l'apparition d'un autre agent dans un espace donné.
|
||||
|
||||
Pour fermer l'application SARL, il faut tuer tous les agents qu'elle contient. Pour fermer un agent, il faut qu'il ne contienne aucun agent dans son contexte interne. Puisque les deux démos sont basées sur une structure holonique il a fallu trouver un moyen de d'arrêter tous les agents. Il faut ainsi transmettre l'événement d'extinction à tous les agents contenu. La solution retenue a est de tuer l'agent s'il ne contiens aucun autre agent et de retransmettre sinon. Dans ce deuxième cas, l'agent vérifie si il reste des agents dans son contexte interne à chaque sortie d'un agent et de se détruire si il ne reste plus aucun agent.
|
||||
|
||||
Lors du développement, il a été fréquent de se heurter à de nombreuses erreurs de *refus de tâche* au niveau du noyau Janus (bibliothèque permettant de faire de l'agent en java et qui est au cœur de l'implémentation du SARL). Cela s'explique par la relative jeunesse du langage et le fait qu'il soit encore en développement. Cela survient généralement lors de la fermeture d'une des démos ou lors de l'utilisation du bouton *stop* pour les feux d'artifice. Dans ces situations, des érreurs de *tâche refusée* empêchent le bon déroulement du programme. Ces erreurs seront réglées dans une future versions de SARL mais m'ont fait perdre plusieurs heures avant de comprendre qu'il n'était pas possible pour moi d'intervenir.
|
||||
|
||||
# Netographie
|
||||
|
||||
Site internet de SARL: [sarl.io](http://sarl.io)
|
BIN
sierpinski_screenshot.png
Normal file
BIN
sierpinski_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
BIN
utbm_logo.png
Normal file
BIN
utbm_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
Loading…
Reference in New Issue
Block a user