-
Notifications
You must be signed in to change notification settings - Fork 12
Tutorial
This section explores in detail our demo-game, which is packaged with the engine. Visit the administration web console to have a look to following explanations.
The game target the mobility domain, where the objective is to incentivate the users of the mobility information application on planning the trips with the app focusing on the promoted transport means and modalities.
The game defined three point concepts
- green leaves, corresponding to the “green” movements in the city
- health, corresponding to healthier transport means (bike, walk)
- p+r (park-and-ride, where the external parkings and bike sharing is promoted.
Also, four badge collections concepts (green leaves, health, p+r, special) are introduced.The collections will be used to collect badges earned on the three point types plus a special one to collect special badges.
Moreover game has an action: save_itinerary.
A set of rules is specified to control the different type of points and to trigger badges and classifiations. For example, the following rule is used to state that the user will gain a “10-green-point” badge when he gains first 10 green points:
More specifically, this rule is executed when player has collected more than 10 points of type green leaves and he hasn’t yet earned the badge 10-point-green. Other two lines in condition part are used only to bound values in variables. When condition is satisfied a log message will be written, the badge 10-point-green is inserted in relative badge collections, a notification will be sent to the system to inform that user has gained a new badge, and the badge collection object will be updated.
rule "10 point green badge"
salience -1000
when
PointConcept(name == 'green leaves', score \>= 10.0)
$bc : BadgeCollectionConcept(name == "green leaves", badgeEarned not contains '10-point-green')
Game( $gameId: id)
Player( $playerId : id)
then
log("apply \\'10-point-green badge\\'");
$bc.getBadgeEarned().add('10-point-green');
insert( new BadgeNotification($gameId,$playerId,'10-point-green'));
update( $bc );
end
Our demo game defined six classification tasks. These tasks are used to calculated the week classifications on green leaves, health and p+r points and the final classifications.
In particular a week classification, green leaves for example, rewards the player with better score on green leaves points of the week. The same thing is done for health and p+r points.
A final classification rewards the better 3 players on single point type.
To simulate the game execution, the engine REST API may be exploited. The API defines the methods for triggering user action, reading the user state, and reading the user notifications. Detailed explanation of the engine REST API interface is [here](REST API engine).
NOTE: to access all the API methods the game ID parameter should be provided. Game ID is generated by the platform and is shown in the game “card” in the console. Use that value to perform the requests.
NOTE: all the API methods defined below are relative to the engine endpoint. In case of the local installation, the http://localhost:8080/gamification should be used. When the SaaS version is used, the following endpoint is due: https://dev.smartcommunitylab.it/gamification.
Initially, the user state is empty. To read the user state the following request may be performed (here and later we will use the value “1” to represent the user ID):
GET /gengine</span>/state/<gameId>/1
{
"playerId":"1",
"gameId":"<gameId>",
"state":{
"BadgeCollectionConcept":[
{ "name":"p+r","badgeEarned":[] },
{ "name":"green leaves", "badgeEarned":[]},
{ "name":"special", "badgeEarned":[] },
{ "name":"health", "badgeEarned":[] }
],
"PointConcept":[
{ "name":"p+r", "score":0.0 },
{ "name":"health", "score":0.0 },
{ "name":"green leaves", "score":0.0 }
]
}
}
In order to reflect the user activities (i.e., planning and performing the trips), the corresponding actions should be triggered. For example, to reflect the fact that the user has performed a trip of 1 km in bicycle:
POST /gengine/execute
{
"gameId": "<gameId>",
"userId": "1",
"actionId": "save_itinerary",
"data": {
"bikeDistance": 1.0
}
}
In the JSON request body we can see the fields used during a engine execution call:
- gameId identifies the game
- actionId activates a set of game rules
- userId identifies the player target of execution
- data is the set of data about user on which execute the action
Calling the player state again, we will see
"playerId":"1",
"gameId":"<gameId>",
"state":{
"BadgeCollectionConcept":[
{ "name":"p+r","badgeEarned":[] },
{ "name":"green leaves", "badgeEarned":[]},
{ "name":"special", "badgeEarned":["zero-impact"] },
{ "name":"health", "badgeEarned":[] }
],
"PointConcept":[
{ "name":"p+r", "score":0.0 },
{ "name":"health", "score":3.0 },
{ "name":"green leaves", "score":5.0 }
]
}
}
So player 1 gained 5 green leaves points, 3 health points and “zero-impact” badge in special badge collection.
How did he gain these points ? Let’s analyze an extract of greenPoints, constants, healthPoints and specialBadges rules, that are the rules involved in this.
rule "update green points"
when
InputData( $bike : data["bikeDistance"], $walk : data["walkDistance"], $bus : data["busDistance"],$train : data["trainDistance"])
$pc : PointConcept(name == "green leaves")
then
log("apply \'update green points\'");
Double bike = $bike != null ? (Double) $bike : 0;
Double walk = $walk != null ? (Double) $walk : 0;
Double bus = $bus != null ? (Double) $bus : 0;
Double train = $train != null ? (Double) $train : 0;
Long dist1 = Math.round(bike + walk);
Long dist2 = Math.round(bus + train);
$pc.setScore($pc.getScore() + green_walk_bike_points * dist1 +
green_bus_train_points * dist2);
update($pc);
end
In greenPoints rule when a data bikeDistance is found, green score of player 1 is incremented of green_walk_bike_points * distance points (green_walk_bike_points is a constant and its value is in rule constants).
# GREEN BONUS
green_walk_bike_points=5
So for 1 kilometer in bicycle player 1 gained 5 points.
The same thing happened for health points assignment.
rule "update health points"
when
InputData( $bike : data["bikeDistance"], $walk : data["walkDistance"])
$pc : PointConcept(name == "health")
then
log("apply \'update health points\'");
Double bike = $bike != null ? (Double) $bike : 0;
Double walk = $walk != null ? (Double) $walk : 0;
Long dist1 = Math.round(walk);
Long dist2 = Math.round(bike);
$pc.setScore($pc.getScore() + health_walk_points * dist1 +
health_bike_points * dist2);
update($pc);
end
# HEALTH BONUS
health_walk_points=10
health_bike_points=3
Let’s see how zero-impact badge is assigned in specialBadges rules
rule "zero impact badge"
salience -1000
when
InputData((data['walkDistance'] != null || data['bikeDistance'] != null)
&& ((data['busDistance'] == null || data['busDistance'] == 0)
&& (data['carDistance'] == null || data['carDistance'] == 0)))
$bc : BadgeCollectionConcept(name == "special",
badgeEarned not contains 'zero-impact')
Game( $gameId: id)
Player( $playerId : id)
then
log("apply \'zero-impact badge\'");
$bc.getBadgeEarned().add('zero-impact');
update( $bc );
insert( new BadgeNotification($gameId,$playerId,'zero-impact'));
end
In detail $bc.getBadgeEarned().add('zero-impact'); added badge to player 1 special badges, insert( new BadgeNotification($gameId,$playerId,'zero-impact')); send a notification in the system.
To see the notification, the notification REST API may be used. For example:
GET /gengine/notification/<gameId>/1
[
{
"gameId":"demo-game",
"playerId":"1",
"timestamp":1427804153766,
"badge":"zero-impact"
}
]