Developing Skills
Defining the class as a skill​
In this section we will be creating a class "FirstClass", that is included in a package named "skill".
-
Create Package
- From the Project Explorer pane, go to your plugin's folder, and then go to the src folder.
- Right click on the src folder. Click on New > Package.
- In the New Java Package dialog, set the Name to "skills".
- Click on Finish. This will create the package "skills".
-
Create class in the Package
- In the Project Explorer, go to the folder of the Plugin. We create the Java class in this package. To do this, right click on the package, then click on New, select Class.
- On the New Java class dialog, set the Name to 'FirstSkill'. Click on Finish.
- Now we have an empty Java class named FirstSkill. Note as well that the GamlAdditions.java file was also automatically added into the gaml/gaml.additions.myFirstPlugin folder.
Using Annotations to define class as a skill​
Annotations are used to link Java methods and classes to GAML language. Note that GAMA annotations are classes defined into the msi.gama.precompiler.GamlAnnotations
class.
We need to tell GAMA that our class "FirstSkill" will be used as skill. To do that we will use Annotation in writing the code of the class. The annotations for skill is described as follows:
@skill​
This annotations Allows to define a new skill (class grouping variables and actions that can be used by agents).
This annotation contains:
-
name (String): a String representing the skill name in GAML (must be unique throughout GAML).
-
attach_to (set of strings): an array of species names to which the skill will be automatically added (complements the "skills" parameter of species).
-
internal (boolean, false by default): return whether this skill is for internal use only.
-
doc (set of @doc, empty by default): the documentation associated to the skill.
- Just before the class declaration, add this line to indicate that this class is a skill named "FirstSkill"
@skill(name = "FirstSkill")
In line 3, a red broken line under the skill word can be seen. This is an error since at this point in the code. Hover your mouse over the error, and the message box would indicate that the skill cannot be resolved to a type.
To correct this error, we take the suggestion of importing 'skill' (msi.gama.precompiler.GamaAnnotations). Click on this option.
It is a good practice to define all the names of plugins/actions/variables in the IKeyword class, which is located in the plugin msi.gama.common.interfaces.IKeyword.java.
In this class you can define a string variable which contain the name of your plugin.
String FIRST_SKILL = "FirstSkill";
Now that we have defined a global string containing the name of the plugin, we can use it in the annotation and in the code of the class.
@skill(name = IKeyword.FIRST_SKILL)
We have now defined that our current class is a skill that can be used in GAMA.
To use our plugin in gaml model, we have to create a species using the skill:
species tutorialSpecies skills:[FirstSkill]
{
}
Defining new attributes for the skill​
Now we have a skill that is empty. So we need to add some variable for the plugin to have a purpose.
To add new attributes to the species that declares this skill, we have to define them before the class using annotation like we did before.
@variable​
This annotations is used to describe a single variable or field.
This annotation contains:
- name (String): the name of the variable as it can be used in GAML.
- type (int): The textual representation of the type of the variable (see IType).
- of (int, 0 by default): The textual representation of the content type of the variable (see IType#defaultContentType()).
- index (int, 0 by default): The textual representation of the index type of the variable (see IType#defaultKeyType()).
- constant (int, false by default): returns whether or not this variable should be considered as non modifiable.
- init (String, "" by default): the initial value of this variable as a String that will be interpreted by GAML.
- depend_on (set of Strings, empty by default): an array of String representing the names of the variables on which this variable depends (so that they are computed before).
- internal (boolean, false by default): return whether this var is for internal use only.
- doc (set of @doc, empty by default): the documentation associated to the variable.
The @vars
annotation contains a set of @variable
elements.
Just like we did before with the declaration of the name of our skill, we can declare globally the name of our incomming new variables, in the IKeyword class.
String FIRST_VARIABLE = "FirstVariable";
String SECOND_VARIABLE = "SecondVariable";
Now that we have defined the names of our variables, we need to declare them in our skill class.
Here is how to declare the variables:
@vars({
@variable(name = IKeyword.FIRST_VARIABLE, type = IType.INT, init = "1"),
@variable(name = IKeyword.SECOND_VARIABLE, type = IType.FLOAT, init = "1.0")
})
In order to access these new attributes, in the GAMA application, you need to define @getter
and @setter
methods:
@getter​
This annotations is used to indicate that a method is to be used as a getter for a variable defined in the class. The variable must be defined on its own (in vars).
This annotation contains:
- value (String): the name of the variable for which the annotated method is to be considered as a getter.
- initializer (boolean, false by default): returns whether or not this getter should also be used as an initializer
@setter​
This annotations is used to indicate that a method is to be used as a setter for a variable defined in the class. The variable must be defined on its own (in vars).
This annotation contains:
- value (String): the name of the variable for which the annotated method is to be considered as a setter.
@getter(IKeyword.FIRST_VARIABLE)
public int getFirstVariable(final IAgent agent) {
return (int) agent.getAttribute(IKeyword.FIRST_VARIABLE);
}
@setter(IKeyword.FIRST_VARIABLE)
public void setFirstVariable(final IAgent agent, final int value) {
agent.setAttribute(IKeyword.FIRST_VARIABLE, value);
}
@getter(IKeyword.SECOND_VARIABLE)
public double getFirstVariable(final IAgent agent) {
return (double) agent.getAttribute(IKeyword.SECOND_VARIABLE);
}
@setter(IKeyword.SECOND_VARIABLE)
public void setFirstVariable(final IAgent agent, final double value) {
agent.setAttribute(IKeyword.SECOND_VARIABLE, value);
}
At this point we can use the variable defined directly in our agent :
species tutorialSpecies skills:[FirstSkill]
{
init
{
write(firstVariable);
write(SecondVariable);
}
}
Defining new actions​
An action (also called primitive
) is basically a Java method that can be called from the GAML language using the same syntax as the one used for calling actions defined in a model. The method should be annotated with @action
, supplying the name of the action as it will be available in GAML.