Une entité représente un élément d'un modèle. Une entité peut posséder un certain nombre de propriétés qui correspondent à l'état de cette entité à un instant donné. On peut définir des entités pour chaque élément susceptible d'interagir avec d'autres éléments du modèles. Les interactions que l'on définit (à travers les relations) dans un modèle sont des intéractions entre entités. Lorsqu'il y a interaction entre entités, leur état peut être affecté, c'est à dire que les valeurs de propriétés de ces entités sont susceptibles de changer.
Une entité peut aussi posséder des services. Un service est une fonction qui permet d'agir sur une ou plusieurs propriétés. On définit des services pour faciliter certaines opérations comme par exemple la conversion d'un système d'unité dans un autre (voir les exemples ci-dessous).
Après avoir défini une catégorie d'entité, on pourra créer des entités individuelles répondant à cette définition. Chaque entité individuelle aura son état propre qui pourra évoluer aux cours d'une simulation.
Définition d'une catégorie d'entité
entity
nom de l'entité{
définitions de propriétés et de services}
Le nom d'une entité doit impérativement commencer par une lettre (majuscule de préférence) mais peut éventuellement être suivi par des chiffres, et ne pas contenir d'espace ni de caractère spéciaux.
On peut placer dans une entité autant de propriétés et de services que l'on veut.
Définition d'une propriété
property
Type nom
Le Type d'une propriété est soit un type simple d'Ocelet ( Integer, Double, Point, etc. ), soit un type composite défini par vous même sous la forme d'une structure.
Le nom d'une propriété doit impérativement commencer par une lettre mais peut éventuellement être suivi par des chiffres, et ne pas contenir d'espace ni de caractère spéciaux.
On ne peut pas utiliser une entité comme type dans la définition d'une propriété.
Attention, lorsque l'on établit une correspondance entre les attributs d'une source de données et les propriétés d'une entité à l'aide d'un datafacer, ces attributs étant toujours des types simples, ils ne peuvent être mis en correspondance qu'avec des propriétés de type simple. Voir la documentation sur les datafacer pour plus de détails.
Définition d'un service
service
(type de retour)? nom(
(liste d'arguments)?)
{
série d'instructions}
Un service est une fonction à laquelle on peut (optionnellement) fournir des valeurs en arguments, et qui peut (optionnellement) retourner un résultat. Un service a accès à toutes les propriétés de l'entité dans laquelle il est défini, il peut lire et changer leur valeur.
Le nom d'un service doit impérativement commencer par une lettre mais peut éventuellement être suivi par des chiffres, et ne pas contenir d'espace ni de caractère spéciaux.
Le type de retour est soit un type simple d'Ocelet, soit un type composite, soit un type d'entité.
Un argument est défini par : type
nom
Le type d'un argument est soit un type simple d'Ocelet, soit un type composite, soit une catégorie d'entité.
Le nom d'un argument doit impérativement commencer par une lettre mais peut éventuellement être suivi par des chiffres, et ne pas contenir d'espace ni de caractère spéciaux.
Si il y a plusieurs arguments dans la liste, il sont séparés par une virgule.
La série d'instructions représente le programme qui réalise ce que doit produire la fonction.
Champ cultivé
entity Champ {
property Polygon contour
property Integer id_parcelle
property String culture
}
La catégorie d'entités Champ ainsi définie ne possède que des propriétés (aucun service). On peut noter la présence d'une propriété de type Polygon
qui permet de décrire la forme du champ et sa position, qui pourra par exemple servir à faire figurer ce champ sur une carte.
On pourrait ajouter des services pour fournir la position du barycentre de ce champ, ou sa surface en hectares :
entity Champ {
property Polygon contour
property Integer id_parcelle
property String culture
service Point getBarycentre() {
return contour.centroid
}
service Double getSurfaceHa() {
return contour.area / 10000
}
}
Station de mesure
entity Station {
property String name
property Point location
property Double tempC
property Double windspeed
property Double winddirection
service Double getTempF() {
return (tempC * 9 / 5) + 32
}
service setTempF( Double tempF ) {
tempC = (tempF - 32) * 5 / 9
}
}
On a ici une entité qui possède des valeurs mesurées par une station météo. La propriété de température est conservée en degrés Celsius. On a ajouté des services pour lire et écrire cette même température en degrés Fahrenheit.
Les définitions de catégories d'entités se trouvent en dehors de tout scenario. A l'intérieur d'un scenario on fait réféfence à ces définitions pour créer une ou plusieurs entités individuelles. La méthode la plus simple consiste à déclarer une variable qui va contenir la nouvelle entité :
let champ1 = new Champ
let champ2 = new Champ
champ1.culture = "céréales"
champ2.culture = "verger"
...
println("Surface de champ 1: "+champ1.getSurfaceHa()+" ha")
On voit que l'on peut accéder directement aux propriétés d'une entité individuelle en séparant le nom de la variable et la propriété par un .
. On peut faire appel à un service de la même façon.
Ainsi dans l'exemple ci-dessus champ1.culture
fait référence à la propriété culture de l'entité stockée dans la variable champ1. L'instruction champ1.culture = "céréales"
a pour effet d'affecter la valeur "céréales" à la propriété culture.
La dernière instruction de cet exemple fait appel au service getSurfaceHa()
pour afficher un phrase à l'écran. Si par exemple le polygone de la propriété contour représente une surface de 85000 m², cette instruction affichera :
Surface de champ 1 : 8.5 ha
Il est possible de construire une série d'entités individuelles à partir d'une source de données, avec l'aide d'un datafacer. Voir la documentation relative aux datafacers pour plus de détails.
Les relations permettent de définir ce qui se passe lorsque des entités intéragissent les unes avec les autres. Dans une relation chaque forme d'interaction est définie à travers une [fonction d'interaction](). Une fonction d'interaction peut affecter l'état des entités impliquées dans une interaction, c'est à dire modifier la valeur de leurs propriétés.
Pour davantage de détails sur ces aspects, veuillez vous reporter à la [documentation relative aux relations]().
Facilite l'usage de println
lorsque l'on désire afficher à l'écran les propriétés d'une entité. Lorsqu'il existe le service toString()
est utilisé pour produire un texte à partir de l'état d'une entité. Cela signifie que si l'on ajoute un service toString()
on peut se contenter d'utiliser l'entité directement dans un appel à print()
ou println()
pour afficher son contenu.
Exemple
entity Sonde {
property Integer id
property Point pos
property Double profondeur
service String toString() {
return "sonde n°"+id+" ("+pos.x+","+pos.y+"): "+profondeur+" m"
}
}
scenario MonModele {
let s1 = new Sonde
...
println(" Mesure "+s1)
}
Cette dernière instruction va afficher à l'écran quelque chose comme :
Mesure sonde n°15 (34.546,234.543): 236.67 m
Les services dont le nom commence par get ou set permettent de faire comme si l'on disposait de propriétés supplémentaires : on accède au nom accolé au set ou au get avec un .
sans avoir à appeler le service lui même.
Il faut noter que le nom accolé au get ou au set doit commencer par une majuscule.
Exemple
Dans l'exemple station de mesure vu plus haut on avait défini des services pour accéder à une temperature en degrés Fahrenheit :
entity Station {
property Double tempC
...
service Double getTempF() {
return (tempC * 9 / 5) + 32
}
service setTempF( Double tempF ) {
tempC = (tempF - 32) * 5 / 9
}
}
Grace à cette convention de nommage, il sera possible dans un scenario d'écrire :
let station1 = new Station
...
station1.tempF = 32.6
let tF = station1.tempF
au lieu de :
station1.SetTempF(32.6)
let tF = station1.getTempF()
et bien sûr dans tous les cas c'est la propriété tempC qui sera modifiée ou lue.
Puisqu'il est possible pour un service de retouner une entité, on peut si nécessaire proposer un service qui construit un clone de l'entité à laquelle il appartient, voire même un clone dont l'état est différent.
Exemple
entity Arbre {
property Point position
property Integer age
service Arbre clone() {
let nouvelArbre = new Arbre
nouvelArbre.position = position
nouvelArbre.age =0
return nouvelArbre
}
}