Ocelet

Entity

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.

Contenu


Définir une catégorie d'entité

Syntaxe

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.


Exemples

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.

Retour en début de page  

Utilisation dans un scenario

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


Création d'entités à partir d'une source de données

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.

Retour en début de page  

Utilisation dans une relation

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]().

Retour en début de page  

Bon à savoir

Ajout d'un service toString() à vos entités

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


Services getXxx() et setXxx()

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.


Clonage

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
  }
}
Retour en début de page