| Author: | Hilaire DROUINEAU <Hilaire.Drouineau at ifremer.fr> |
|---|---|
| Revision: | $Revision: 1.11 $ |
| Date: | $Date: 2006/05/02 11:47:00 $ |
L'ecmascript est comme son nom l'indique un langage dit de script, c'est à dire qu'il n'est pas compilé avant son exécution (Pareil que R, VisualBasic...). L'EcmaScript va être utile dans ISIS-Fish à principalement trois niveaux: - pour spécifier des équations (par exemple, équation de croissance, de mortalité naturelle, de migration, de reproduction) - pour modifier les valeurs de certains paramètres sans avoir à modifier la base de données à travers de scripts de présimulations. Ceci est particulièrement intéressant dans le cadre d'analyse de sensibilité - pour coder des règles de gestion.
Si la connaissance de l'EcmaScript n'est pas complètement indispensable à l'utilisation de ISIS-Fish, avoir quelques notions s'avère fort utile.
Comme pour tout langage de programmation, il est particulièrement intéressant de décrire (documenter) un code afin de le rendre plus compréhensible pour un autre utilisateur ou lors d'une réutilisation postérieure. Le commentaire doit donc être un texte apparaissant dans le code mais non exécuté lors de l'exécution. Un commentaire peut-être ajouté de deux manières en Ecmascript comme détaillé dans l'exemple.
Ex:
var a=2 //tout ce qui figure sur cette ligne après le signe est un commentaire /*je peux mettre un commentaire sur plusieurs lignes entre antislash étoile et étoile antislash*/ var b=3;
En Ecmascript, les variables quelque soit leur type se déclarent d'une seule et même façon.
L'instruction:
var NouvelleVariable;
crée une nouvelle variable appelée NouvelleVariable (attention: les majuscules comptent).
Il existe cinq types de données primitives en EcmaScript: undefined, null, Boolean, Number et String, admettent en revanche plusieurs valeurs différentes.
undefined: variable qui n'a pas encore de valeurs
null: variable vide ou fonction non gérée
string: chaîne de caractères
booléen: true ou false
numeric: un nombre
L'affectation d'une valeur à une variable se fait avec l'opérateur =.
Les opérations mathématiques classiques telles que +, -, *, / sont définies sur les variables numériques, ainsi que l'opérateur % qui donne le reste de la division euclidienne
Ex:
var a=2; var b=5; a+b; //renvoie 7 a-b; //renvoie -3 b%a //renvoie 1
++ et -- permettent d'incrémenter ou de diminuer d'une unité une variable numérique.
Ex:
var a=2 a++; //a vaut 3 a--; //a vaut 2
+= , -= , /= et *= prend la valeur de gauche y additionne (ou soustrait, ou divise ou multiplie) la valeur de droite et affecte le résultat à la variable de gauche.
Ex:
var a=2; a+=3; //a vaut 5
Pour les chaînes de caractères, l'opérateur + (+= rajoute à la fin) permet de concaténer plusieurs chaînes.
Les opérateurs de comparaisons renvoient un booléen si la comparaison est vraie ou fausse. Attention ces opérateurs ne marchent que sur des numeric.
| Opérateurs | Type de comparaison |
|---|---|
| > | Supérieur strict |
| < | Inférieur strict |
| <= | Supérieur ou égal |
| >= | Inférieur ou égal |
| == | Strictement égal |
| != | Différent de |
| syntaxe: | opérande 1 && opérande 2
|
|---|
| syntaxe: | opérande 1 || opérande 2
|
|---|
{//début du bloc
var a=3;
a++;
}// fin du bloc
if (a==1){
//bloc si a est égal à 1
if (b<2){
b++; //instruction réalisée si en plus b est inférieur à 2
}
else{
b--; //instruction réalisée si en plus b est supérieur ou égal à 2
}
} //fin du bloc if
else if (a>0 && b>0){
b++; //bloc réalisé si a est différent de 1 mais supérieur à 0 et que b est inférieur à 0
a++;
}
else {
b--; //bloc réalisé si a est différent de 1, et si a et b ne sont pas strictement positifs
}
On note dans cet exemple l'utilisation des opérateurs logiques. D'autre part, pour la clarté du code, il est conseillé de décaler les blocs (deux espaces ou une tabulation) selon leur niveau d'imbrication.switch (Option){ //
case 1:
a++; //ce bloc est réalisé si Option vaut 1
break;
case 2:
b++;
break; //ce bloc est réalisé si Option vaut 2
}
Chaque bloc doit se terminer par l'instruction break;.var a=1;
for (var i=1; i<3; i++){/*le compteur i vaut 1 en début de simulation, on
renouvelle l'opération tant que i<3 et i augmente d'
une unité à chaque opération*/
a++;
} //en sortie a vaut 3
var a=1;
var i=1;
while (i<3){
a++;
i++;
} // le résultat est ici exactement le même que dans l'exemple précédent
var a=1;
var i=1;
do{
a++;
i++;
} while(i<3); // attention au ;
var Thon=PopulationFactory.findByName('Thon'); //On récupère la population
//dont le nom est Thon
Un descriptif des différentes classes disponibles dans ISIS est consultable en ligne:var copie=MatrixFactory.create(original);
var mois= new Packages.fr.ifremer.nodb.Mois(3); //pour créer un nouveau mois
//il faut mettre new puis le
//nom du package (on le trouve //dans l'api de la classe).Il existe encore un dernier type d'objets bien utile (enfin certains par exemple hashmap, arraylist) qui sont des objets java. Leur api est à la page:http://java.sun.com/j2se/1.5.0/docs/api/Pour construire un de ces objets on procède de la même manière que les précédents. Pour info une arraylist est une liste contenant des objets (elle sert pas mal dans certains cas où la dbcollection ne marche pas). Une hashmap est une espèce de tableau à deux colonnes, dans la colonne de gauche on met un objet clé (par exemple un mois) auquel on associe dans la colonne de droite un objet dit valeur (par exemple une zone), ça permet de rechercher la valeur associée à une clé (par exemple récupérer la zone associée au mois de janvier).var Thon=PopulationFactory.findByName('Thon');
var Merlu=PopulationFactory.findByName('Merlu');
if (Melu.equals(Thon)){
writeln ('bizarre'); //ce bloc ne sera pas exécuté
}
else {
writeln ('les thons sont différents de merlus'); //celui-ci oui, pour la
//méthode writeln voir à
//la fin
}
result = ECMAScript(# //corps de la fonction: DOIT renvoyer un résultat #); resultNe vous embêtez pas trop à comprendre ce que veut dire ce qu'il y a autour du corps, dans la version 3 on devrait pu avoir à mettre tout ça.
result=ECMAScript(# Linf = 100.0; K = 0.0010; T0 = -1.0; Linf*(1.0-Exp((-K*((age/12)-T0)))); #); result
result=ECMAScript(# Linf = 48.0; K = 0.14; t0 = 1.0; ((-t0-((1.0/K)*Ln((1.0-(longueur/Linf)))))*12.0); #); result
r = ECMAScript(#
for(var izone=0; izone<zoneRepro.size(); izone++){
var zone=zoneRepro.get(izone); // on prend le izone-ième élément de la liste
var tot = 0.0; //on veut compter le nombre d'oeufs total produit dans la zone
for (var iclasse=0; iclasse=pop.getClasses();iclasse++){
//on va sommer tous les oeufs produits par toutes les classes
var classe=pop.getClasses().get(iclasse);
tot=tot+classe.getCoefficientFecondite()*N.getValue(classe,zone);
//on multiplie l'effectifs de la classe dans la zone par la fécondité et on rajoute à tot
}
//on a finit la boucle sur les classes, on a donc tous les oeufs produits
result.setValue(zr, tot*prepro);
//on remplit la matrice result, on multiplie par prepro pour prendre en compte la proportion
//de reproduction pour le mois courant
}
// on retourne une valeur qui ne sert a rien
// puisque result sera utilisé
0;
#);
r
result = ECMAScript(#
var chaine=Packages.java.lang.String; //une petite astuce qui évite de refaire à chaque coup
//new Packages.java.lang.String
var nomZone=new chaine(zone.getNom()); //on convertit les chaînes primitives en
//java.lang.String pour pouvoir bénéficier de la
// méthode equals()
if (classe == -1) { //cas de la classe prérecrutée
if (nomZone.equals(new chaine('Repro31'))) 3.5;
else 2.5;
}
else if (classe.getAge() == 0){ //cas de la classe 0
if (nomZone.equals(new chaine('Recru2'))) 2;
else 2.3;
}
else 1.2;
#);
result
#Migration
result=ECMAScript(#
if (classe.getAge()==1){
var chaine=Packages.java.lang.String;
var nomZoneDepart=new chaine(zoneDepart.getNom());
var nomZoneArrive=new chaine(zoneArrive.getNom());
if (nomZoneDepart.equals(new chaine('Recru2')) && nomZoneArrive.equals(new chaine('Recru1'))){
var diff=N.getValue(classe,zoneDepart)-N.getValue(classe,zoneArrive);
if ((1/diff)>1) {
1/diff; //on a une proportion qui dépend de la diff d'effectifs
//entre zoneDep et Zone arrive
}
else 0;
}
else 0;
}
else 0;
#);
result
#Immigration
result=ECMAScript(#
if (classe.getAge()==1){
var chaine=Packages.java.lang.String;
var nomZoneArrive=new chaine(zoneArrive.getNom());
if (nomZoneArrive.equals(new chaine('gironde'))){
N.getValue(classe,zoneArrive); //il en rentre autant qu'il y en avait
}
else 0;
}
else 0;
#);
result
#Emigration
result=ECMAScript(#
if (classe.getAge()==1){
var chaine=Packages.java.lang.String;
var nomZoneDepart=new chaine(zoneDepart.getNom());
if (nomZoneDepart.equals(new chaine('Repro31'))){
if (N.getValue(classe,zoneDepart)>10) 0.5; //Des que y en a un peu trop,
//ils s'en vont
}
else 0;
}
else 0;
#);
result
result=ECMAScript(# var SR=10; var L50=27; var beta=2*Ln(3)/SR; var alpha=-beta*L50; 1/(1+Exp(-alpha-beta*longueur)); #); result
var Thon=PopulationFactory.findByName('Thon'); //j'aime bien les thons!
var classe0=Thon.getClasses().get(0); //première classe du thon
classe0.setPoidsMoyen(13); //dans ma simu, le poids moyen vaudra 13
Comme ça ça paraît déjà pas mal intéressant, mais on peut faire encore plus fort!new Array("var Thon = PopulationFactory.findByName('Thon'); var classe0 = Thon.getClasses().get(0) ; classe0.setPoidsMoyen(13);",
"var Thon = PopulationFactory.findByName('Thon') ; var classe0 = Thon.getClasses().get(0) ; classe0.setPoidsMoyen(12);",
"var Thon = PopulationFactory.findByName('Thon') ; var classe0 = Thon.getClasses().get(0) ; classe0.setPoidsMoyen(11);")
à chaque case du tableau correspondra une simulation avec les valeurs 13, puis 12 puis 11 de poids pour la classe 0.Remarque, on peut aussi faire comme ça:var result = new Array();
for (var i=1; i<=3; i++){
var temp="var Thon = PopulationFactory.findByName('Thon');var classe0=Thon.getClasses().get(0);classe0.setPoidsMoyen(";
switch (i){
case 1:
temp+=13;
break;
case 2:
temp+=12;
break;
case 3:
temp+=11;
break;
}
temp+=");"
result.push(temp); //on met en fin de tableau la chaîne temp
}
result;
Remarque: temp est une chaîne de caractères donc entourée de guillemets, si à l'intérieur on a aussi besoin de caractères (par exemple ici findByName('Thon')), il faut utiliser ' pour ne pas qu'il puisse y avoir de confusion.bon Ok comme ça ça paraît un peu compliqué mais vous verrez que si un jour vous avez besoin de faire un vrai plan de simulations, c'est l'outil qu'il vous faut.