Skip to content
Snippets Groups Projects
Commit 78811357 authored by Rémi PAPIN's avatar Rémi PAPIN
Browse files

Merge branch 'master' of...

parents 50b99f19 651199db
No related branches found
No related tags found
No related merge requests found
Pipeline #9943 passed
File added
......@@ -29,21 +29,110 @@ Then, he generate two randoms answers following the right answer.
## Duel
### On launch
### On launch
In order to find a valid reference period we search for a period which is defined by the duel duration.
We check the most recent period first if it's complete and then we go farther and farther in the time if the ones before got missing values.
We also define a threshold for a maximum old period (6 months for the moment determined in the code ==> hardcoding).
If the thresold is reached and no valid period was found, we alert the user that he can't launch the duel and have to wait before he can retry this process.
### On going
### On going
Every time the user go into the duel mode, we are checking if the duel is finished.
if (actualDate - startDate) > duelDuration, the duel is done.
Every time the user go into the duel mode, we are checking if the duel is finished.
if (actualDate - startDate) > duelDuration, the duel is done.
### On finish
### On finish
Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge.
Once the state of the duel is set to DONE, we save the user result and determine if he wins (userComsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge.
## Challenge data managment
We handle data storage according to the following process :
The folder /db contains all the JSON entities that are directly stored in the couchDB during the initialization process that is executed in the splash screen. They are stored under their related doctype.
## Initialization and Updating
During the initialization process, we store a hash for each dataEntity that is likely to be changed or updated. The hash is stored in the userProfile.
```json
[
{
"ecogestureHash": "",
"challengeHash": "",
"duelHash": "",
"isFirstConnection": true,
"haveSeenFavoriteModal": false,
"haveSeenOldFluidModal": false,
"haveSeenLastReport": true,
"sendReportNotification": false,
"monthlyReportDate": "0000-01-01T00:00:00.000Z"
}
]
```
This way, once the initialization is launched, we compare the hash we have in the current userProfile with the one generated from the entity located in /db folder, and if they are different we update the couchDB with the new data.
### dataEntity vs userData
In the project, you'll see two versions for the same data. The dataEntity (quizEntity, challengeEntity, ...) is the data stored in the db folder and in the couchDB. These data are only edited in the couchDB when we update a challenge/quiz/duel or add a new one.
The userData (userChallenge, userQuiz...) is created from the entity and extended with user's data, such as his progress, his consumption data, goals, fails etc.
Using this 2 structures allows us to keep user's datas when we'll update the application, by editing just the entities.
## Challenges
We can find the file challengeEntity.json in the /db folder. This file contains an array of challenges, and each of them includes relationships to duels, quiz, missions and actions.
### Relationships
Relationships is a functionality made by cozy, they are built with the name of the relation, containing a "data" object, itself containing the id of the related item and its doctype "\_type". Using this allows us to reduce the size of the stored items and increase readability.
You can see more on [cozy documentation](https://docs.cozy.io/en/cozy-doctypes/docs/io.cozy.apps.suggestions/#relationships).
```json
"relationships": {
"quiz": {
"data": { "_id": "QUIZ001", "_type": "com.grandlyon.ecolyo.quiz" }
},
"duel": {
"data": { "_id": "DUEL001", "_type": "com.grandlyon.ecolyo.duel" }
}
}
```
### UserData creation
Once a user launch a challenge in the Ecolyo app, we create a userChallenge and store it in the couchDB under the doctype '**com.grandlyon.ecolyo.userchallenge'.** During this process, the objects related to the challenge (quiz, duel, mission, action) will be be converted to an user version which contains informations about the user progress, the fluids connected and so on. So we have now a userChallenge that contains a userQuiz, a userDuel, etc. instead of relations.
To illustrate this, let's show the conversion of quizEntity to userQuiz :
```jsx
DuelEntity {
id: string
title: string
description: string
duration: Duration
}
```
Becomes :
```jsx
UserQuiz {
id: string
title: string
description: string
duration: Duration
threshold: number
state: UserDuelState
startDate: string | null
fluidTypes: FluidType[]
userConsumption: number
}
```
### Data managment schema
![Data Scheme](/img/challengeFlow.png)
!!! info ""
:construction: Section under Construction :construction:
\ No newline at end of file
:construction: Section under Construction :construction:
## EGL Konnector
This konnector fetches consumptions measures from EGL API.
The EGL API allows us to get a user's consumption data gathered by it's connected water meter "Téléo".
You can clone the project [here](https://forge.grandlyon.com/web-et-numerique/llle_project/egl-konnector).
You should also check Cozy's official documentations for konnectors :
[https://docs.cozy.io/en/tutorials/konnector/getting-started/](https://docs.cozy.io/en/tutorials/konnector/getting-started/)
API Url for Development : [https://agence-rec.eaudugrandlyon.com](https://agence-rec.eaudugrandlyon.com/)
API Url for Production : [https://agence.eaudugrandlyon.com/ws](https://agence.eaudugrandlyon.com/ws)
## Authentication
In order to authenticate to the EGL API we have to request the following route
Method : **POST**
Authentication Route : **/connect.asp**
```json
"headers":
{
{
"AuthKey": <your-auth-key>,
"Content-Type": "application/x-www-form-urlencoded"
}
}
```
```json
"body":
{
"mode": "formdata"
{
"login": <your-login>,
"pass": <your-password>
}
}
```
Once you've sent this request the API should answer with a code 100 if everything is ok and provides you a valid **_token_** and **_num_abt_** that you will use later in order to get data.
```json
{
"codeRetour": 100,
"libelleRetour": "Connecté",
"resultatRetour": {
"num_abt": 1895683,
"token": "897555754A703055397897456568776E32704C3953514F5R"
}
}
```
## Fetch Data
In order to get data from the EGL API we have to request the following route :
Method : **POST**
Authentication Route : **/getAllAgregatsByAbonnement.aspx**
```json
"body":
{
"mode": "formdata"
{
"login": <your-login>,
"pass": <your-password>
}
}
```
```json
"body":
{
"mode": "formdata"
{
"token": "897555754A703055397897456568776E32704C3953514F5R",
"num_abt": 1895683,
"date_debut": MM/JJ/YYYY,
"date_fin": MM/JJ/YYYY
}
}
```
The dates must be valid dates otherwise you'll get an error
There answer will provides you an array of data day by day with the value got by the water meter 'ValeurIndex' at this moment.
```json
{
"codeRetour": 100,
"libelleRetour": "L'opération a réussi",
"resultatRetour": [
{
"DateReleve": "2020-07-01T00:00:00+02:00",
"TypeAgregat": "R",
"ValeurIndex": 562362
},
{
"DateReleve": "2020-07-02T00:00:00+02:00",
"TypeAgregat": "R",
"ValeurIndex": 562432
}
]
}
```
You'll have to subtract a day value with the previous's to get a consumption for a given day.
### TypeAgregats
- "R", means the real value
- "A", means an anomaly
- "D", means a water meter changing
- "V"
- "X"
- "T", means pending data
If you're looking for more information about the API, checkout the [complete API documentation](/documents/egl-api-doc.pdf)
### Usage
TODO : add explanation of how we manage data in the konnector
!!! info ""
:construction: Section under Construction :construction:
\ No newline at end of file
:construction: Section under Construction :construction:
This konnector fetches consumptions measures from Enedis API. This is an Oauth Konnector, meaning the authentification performed to access all data is made following an Oauth2 protocol.
You can clone the project [here](https://forge.grandlyon.com/web-et-numerique/llle_project/enedis-konnector).
You should also check Cozy's official documentations for konnectors :
[https://docs.cozy.io/en/tutorials/konnector/getting-started/](https://docs.cozy.io/en/tutorials/konnector/getting-started/)
[https://docs.cozy.io/en/tutorials/konnector/oauth/](https://docs.cozy.io/en/tutorials/konnector/oauth/)
## Enedis Konnector
The Oauth protocol does not take place in the konnector code, therefore it is also important to take a look at the [proxy](../proxy/description.md) to fully understand all the interactions that will be told below.
All the actions performed by the stack are targetted from pre-registered paramaters, here is the list of all parameters needed by the stack to perform the Oauth protocol and allow the konnector to fetch data.
On its first launch, following the Oauth Client Connect authentification.
- The cozy stack calls the **authentification_endpoint** and start the oauth protocol, see [proxy doc](../proxy/description.md).
- The account has now an access_token and an id_token from the oauth call
!!! info ""
id*token is only given when requesting the token endpoint in \_authorization_code* grant_type.
This token holds several meta datas, including the pce_id (id of user's meter) that will be needed further to fetch user's datas.
- Konnector starts, fails to find a pce_id in database on first launch therefore decodes the id_token to store the pce_id in db (see [addData](https://docs.cozy.io/en/cozy-konnector-libs/api/#adddata_1)).
- Konnector restarts, this time knowing a pce_id, it fails to fetch datas because the access_token from oauth call has a reduced scope (only scoping for meta data requests).
- Konnector launches a refresh call, the proxy knows to answer it with a _client_credentials_ grant_type call to grdf /access_token.
- Konnector restarts with everyting needed in database to fetch datas and store them in couchdb.
- Further jobs will not need to change scope again and will only ask for refresh tokens.
## Enedis API
API Url for Production : [https://gw.prd.api.enedis.fr](https://gw.prd.api.enedis.fr)
Enpoints :
- /v4/metering_data/consumption_load_curve
- /v4/metering_data/daily_consumption
## Timeseries doctypes
### Description
Each fluid has its own doctype wildcard and one doctype per time step. Each available time step for a fluid depends of the available data from the energy provider. Here are the different time step:
* minute
* hour
* day
* month
* year
- minute
- hour
- day
- month
- year
### Doctype
Here are the available doctypes:
Fluid type | Doctype wildcard | Doctypes
---------- | -----------------|---------
electricity fluid / enedis | **`com.grandlyon.enedis.*`** | **`com.grandlyon.enedis.minute`**<br>**`com.grandlyon.enedis.hour`**<br>**`com.grandlyon.enedis.day`**<br>**`com.grandlyon.enedis.month`**<br>**`com.grandlyon.enedis.year`**
gaz fluid / grdf | **`com.grandlyon.grdf.*`** | **`com.grandlyon.grdf.hour`**<br>**`com.grandlyon.grdf.day`**<br>**`com.grandlyon.grdf.month`**<br>**`com.grandlyon.grdf.year`**
water fluid / eau du grand lyon | **`com.grandlyon.egl.*`** | **`com.grandlyon.egl.day`**<br>**`com.grandlyon.egl.month`**<br>**`com.grandlyon.egl.year`**
| Fluid type | Doctype wildcard | Doctypes |
| ------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| electricity fluid / enedis | **`com.grandlyon.enedis.*`** | **`com.grandlyon.enedis.minute`**<br>**`com.grandlyon.enedis.hour`**<br>**`com.grandlyon.enedis.day`**<br>**`com.grandlyon.enedis.month`**<br>**`com.grandlyon.enedis.year`** |
| gaz fluid / grdf | **`com.grandlyon.grdf.*`** | **`com.grandlyon.grdf.hour`**<br>**`com.grandlyon.grdf.day`**<br>**`com.grandlyon.grdf.month`**<br>**`com.grandlyon.grdf.year`** |
| water fluid / eau du grand lyon | **`com.grandlyon.egl.*`** | **`com.grandlyon.egl.day`**<br>**`com.grandlyon.egl.month`**<br>**`com.grandlyon.egl.year`** |
### Structure
Field | Type | Description
----- | -----|------------
load | number | load (in kWh or L)
minute | number | minute of the date<br>*set to 0 except for minute serie*
hour | number | hour of the date<br>*set to 0 except for minute and hour series*
day | number | day of the date<br>*set to 1 for month and year series*
month | number | month of the date<br>*set to 1 for year series*
year | number | year of the date
| Field | Type | Description |
| ------ | ------ | ---------------------------------------------------------------- |
| load | number | load (in kWh or L) |
| minute | number | minute of the date<br>_set to 0 except for minute serie_ |
| hour | number | hour of the date<br>_set to 0 except for minute and hour series_ |
| day | number | day of the date<br>_set to 1 for month and year series_ |
| month | number | month of the date<br>_set to 1 for year series_ |
| year | number | year of the date |
### Example
```
{
"load": 770.18,
......@@ -43,52 +47,74 @@ year | number | year of the date
## User profile
### Description
This doctype is used to store all information about the user.
### Doctype
**`com.grandlyon.ecolyo.userprofile`**
**`com.grandlyon.ecolyo.profile`**
### Structure
Field | Type | Description
----- | -----|------------
level | number | challenge level of the user
challengeTypeHash | string | Hash used to verify the content of challenge type
ecogestureHash | string | Hash used to verify the content of ecogesture
haveSeenWelcomeModal | boolean | flag to inform is the user have seen the welcome modal
| Field | Type | Description |
| ---------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| id | string | Profile id |
| ecogestureHash | string | Hash used to verify the content of ecogestures |
| challengeHash | string | Hash used to verify the content of challenges |
| duelHash | string | Hash used to verify the content of duels |
| quizHash | string | Hash used to verify the content of quiz |
| isFirstConnection | boolean | Boolean used to inform if the user connects for the first time |
| haveSeenFavoriteModal | boolean | Boolean used to inform if user has seen the favorite modal |
| haveSeenLastReport | boolean | Boolean used to inform if user has seen the last report |
| haveSeenOldFluidModal | Datetime or boolean | Used to inform if user has seen the modal display when his data are too old. Its value is false or a DateTime when he saw it |
| sendReportNotification | boolean | Boolean used to inform if user has seen the report notification |
| monthlyReportDate | DateTime | Date of the last monthly report |
### Example
```
{
"challengeTypeHash": "c10bbfec554e735d58a5d7009c9964e4a6bc4c65",
"ecogestureHash": "71d475cead14a465d697de596ad21e9aebf3def2",
"haveSeenWelcomeModal": true,
"level": 2
"id": "0e016e853592e18155e87b85ce00a33a",
"challengeHash": "4cbcafe514788757c377534f1a407e022c29e38c",
"duelHash": "48371ffabb2853b0503b882f11e1fa8e730bac76",
"ecogestureHash": "9798a0aaccb47cff906fc4931a2eff5f9371dd8b",
"haveSeenFavoriteModal": true,
"haveSeenLastReport": true,
"haveSeenOldFluidModal": false,
"isFirstConnection": false,
"monthlyReportDate": "2021-01-03T00:00:00.000+01:00",
"quizHash": "11372a56c03edef1d6656f8a76d5ec457174f2c1",
"sendReportNotification": false
}
```
## Ecogesture
### Description
This doctype is used to store ecogestures.
### Doctype
**`com.grandlyon.ecolyo.ecogesture`**
### Structure
Field | Type | Description
----- | -----|------------
shortName | string | short name of the ecogesture
longName | string | long name of the ecogesture
shortDescription | string | short description of the ecogesture
longDescription | string | long description of the ecogesture
usage | string | usage of the ecogesture
fluidTypes | FluidType[] | Array of fluid type on which ecogesture can have an impact<br><br>*FluidType enum:*<br>- *ELECTRICITY = 0*<br>- *WATER = 1*<br>- *GAS = 2*<br>- *MULTIFLUID = 3*
nwh | number | negawattheure - impact of the ecogesture from 0 to 10
pack | number | pack number of the ecogesture (1 pack contain 2 ecogestures)
iconName | string | icon name for ecogesture
unlocked | boolean| (Optional) state for unlocked ecogesture
| Field | Type | Description |
| ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| shortName | string | short name of the ecogesture |
| longName | string | long name of the ecogesture |
| shortDescription | string | short description of the ecogesture |
| longDescription | string | long description of the ecogesture |
| usage | string | usage of the ecogesture |
| fluidTypes | FluidType[] | Array of fluid type on which ecogesture can have an impact<br><br>_FluidType enum:_<br>- _ELECTRICITY = 0_<br>- _WATER = 1_<br>- _GAS = 2_<br>- _MULTIFLUID = 3_ |
| nwh | number | negawattheure - impact of the ecogesture from 0 to 10 |
| pack | number | pack number of the ecogesture (1 pack contain 2 ecogestures) |
| iconName | string | icon name for ecogesture |
| unlocked | boolean | (Optional) state for unlocked ecogesture |
### Example
```
{
"shortName": "Contrôle du nuage",
......@@ -104,110 +130,327 @@ unlocked | boolean| (Optional) state for unlocked ecogesture
}
```
## Challenge type
## Challenge
### Description
This doctype is used to store all available challenges.
This doctype is used to store all challenges.
### Doctype
**`com.grandlyon.ecolyo.challengetype`**
**`com.grandlyon.ecolyo.challenge`**
### Structure
Field | Type | Description
----- | -----|------------
type | TypeChallenge | type of challenge<br><br>*TypeChallenge enum:*<br>- *CHALLENGE = 0*<br>- *ACHIEVEMENT = 1*
title | string | title of the challenge
description | string | description of the challenge
level | number | level needed to unlock the challenge
duration | Duration | duration. (Duration from luxon)
fluidTypes | FluidType[] | Array of fluid type associated to the challenge<br><br>*FluidType enum:*<br>- *ELECTRICITY = 0*<br>- *WATER = 1*<br>- *GAS = 2*<br>- *MULTIFLUID = 3*
relationships | any | relation to available ecogestures for the challenge<br><br>*"availableEcogestures": {*<br>*"data": Ecogesture[]*<br>*}*
| Field | Type | Description |
| ------------- | ------ | ------------------------------------------------- |
| \_id | string | challenge id - respect the format _CHALLENGE000X_ |
| title | string | title of the challenge |
| description | string | description of the challenge |
| target | number | The number of stars required to unlock the duel |
| relationships | any | relation to quiz and duel |
### Example
```
{
"type": 1,
"title": "Ecolyo Royal",
"description": "Connecter l'application Ecolyo à votre distributeur d'énergie",
"level": 1,
"duration": {
"days": 0
},
"fluidTypes": [
0,
1,
2
],
{
"_id": "CHALLENGE0001",
"title": "Nicolas Hublot",
"description": "foobar",
"target": 15,
"relationships": {
"availableEcogestures": {
"data": [
{
"_id": "0085",
"_type": "com.grandlyon.ecolyo.ecogesture"
},
{
"_id": "0092",
"_type": "com.grandlyon.ecolyo.ecogesture"
}
]
}
"quiz": {
"data": { "_id": "QUIZ001", "_type": "com.grandlyon.ecolyo.quiz" }
},
"duel": {
"data": { "_id": "DUEL001", "_type": "com.grandlyon.ecolyo.duel" }
}
}
}
}
```
## User challenge
### Description
This doctype is used to store all additionnal information about a challenge started or ended by the user.
### Doctype
**`com.grandlyon.ecolyo.userchallenge`**
### Structure
Field | Type | Description
----- | -----|------------
startingDate | string | starting date of the the challenge
endingDate | string | ending date of the challenge
state | ChallengeState | state of the challenge
maxEnergy | number |
currentEnergy | number |
badge | BadgeState | state of the badge<br><br>BadgeState enum<br>- *FAILED = 0*<br>- *SUCCESS = 1*
fluidTypes | FluidType[] | fluid types set when user launch the challenge<br><br>*FluidType enum:*<br>- *ELECTRICITY = 0*<br>- *WATER = 1*<br>- *GAS = 2*<br>- *MULTIFLUID = 3*
relationships | any | relation to the challenge type and selected ecogestures for the challenge<br><br>*"challengeType": {*<br>*"data": ChallengeType[]*<br>*}*<br><br>*"selectedEcogestures": {*<br>*"data": Ecogesture[]*<br>*}*
| Field | Type | Description |
| ---------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| id | string | userChallenge id |
| title | string | userChallenge title |
| state | UserChallengeState | state of the challenge<br><br>UserChallengeState enum<br>- _LOCKED = 0_<br>- _UNLOCKED = 1_<br>- _ONGOING = 2_<br>- _DUEL = 3_<br>- _DONE = 4_ |
| target | number | Number of stars required to unlock the duel |
| progress | number | Number of stars earned by the user |
| quiz | UserQuiz | Complete Quiz object with progress |
| duel | UserDuelEntity | Complete Duel object with progress included |
| success | UserChallengeSuccess | Success state of the challenge<br><br>UserChallengeSuccess enum<br>- _ONGOING = 0_<br>- _LOST = 1_<br>- _WIN = 2_ |
| startDate | string null | starting date of the the challenge |
| endingDate | string null | ending date of the challenge |
### Example
```
{
"state": 1
"badge": 1,
"currentEnergy": -1,
"startingDate": "0001-01-01T00:00:00.000Z",
"endingDate": "2020-06-16T00:00:00.000+02:00",
"maxEnergy": -1,
"relationships": {
"challengeType": {
"data": {
"_id": "CHA00000001",
"_type": "com.grandlyon.ecolyo.challengetype"
}
},
"selectedEcogestures": {
"data": [
{
"_id": "0085",
"_type": "com.grandlyon.ecolyo.ecogesture"
},
{
"_id": "0092",
"_type": "com.grandlyon.ecolyo.ecogesture"
}
]
}
"_id": "eae3a79a05d677a739bdd2b46b009936",
"description": "foobar",
"duel": {
"description": "Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION € en 1 semaine",
"duration": {
"days": 7
},
"fluidTypes": [
0,
1,
2
],
"id": "DUEL001",
"startDate": null,
"state": 4,
"threshold": -1,
"title": "Nicolas Hublot",
"userConsumption": 0
},
"endingDate": null,
"id": "CHALLENGE0001",
"progress": 15,
"quiz": {
"customQuestion": {
"interval": 30,
"period": {},
"questionLabel": "Quel jour ai-je le plus consommé la semaine dernière ?",
"result": 1,
"timeStep": 20,
"type": 0
},
"id": "QUIZ001",
"questions": [
{
"answers": [
{
"answerLabel": "Vapeur d'eau",
"isTrue": false
},
{
"answerLabel": "Fumée",
"isTrue": false
},
{
"answerLabel": "Gouttelettes d'eau et cristaux de glace",
"isTrue": true
}
],
"explanation": "Les nuages sont constitués de gouttelettes d'eau et parfois aussi de cristaux de glace",
"questionLabel": "De quoi les nuages sont-ils constitués ?",
"result": 1,
"source": "string"
},
{
"answers": [
{
"answerLabel": "86 km",
"isTrue": true
},
{
"answerLabel": "78 km",
"isTrue": false
},
{
"answerLabel": "56 km",
"isTrue": false
}
],
"explanation": "L’aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant alimenté la ville en eau, et celui dont les structures sont le mieux conservées. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rhône",
"questionLabel": "Quelle longueur faisait l’aqueduc du Gier pour acheminer l’eau sur Lyon à l’époque romaine ?",
"result": 1,
"source": "string"
},
{
"answers": [
{
"answerLabel": "Crémieux",
"isTrue": false
},
{
"answerLabel": "Crépieux-Charmy",
"isTrue": true
},
{
"answerLabel": "Charly",
"isTrue": false
}
],
"explanation": "Crépieux-Charmy est le principal champ captant de la Métropole de Lyon",
"questionLabel": "Quelle est le nom du principal champ de captage d’eau potable de la Métropole ?",
"result": 1,
"source": "string"
},
{
"answers": [
{
"answerLabel": "Pompe à air",
"isTrue": false
},
{
"answerLabel": "Pompe à cordes",
"isTrue": true
},
{
"answerLabel": "Pompe de Cornouailles",
"isTrue": false
}
],
"explanation": "Mise en fonctionnement en 1856, 3 pompes à vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.",
"questionLabel": "Quelle type de pompes étaient utilisées à l'usine des eaux de Caluire jusqu'en 1910 ?",
"result": 1,
"source": "string"
}
],
"result": 5,
"state": 2
},
"startDate": "2021-01-04T00:00:00.000Z",
"state": 3,
"success": 0,
"target": 15,
"title": "Nicolas Hublot"
}
```
## Quiz
### Description
This doctype is used to store all quiz.
### Doctype
**`com.grandlyon.ecolyo.quiz`**
### Structure
| Field | Type | Description |
| -------------- | -------------------- | ------------------------------------------- |
| \_id | string | quiz id - respect the format _QUIZ00X_ |
| questions | QuestionEntity[] | Array of questions entities |
| customQuestion | CustomQuestionEntity | Custom question based on user's consumption |
### Example
```
{
"_id": "QUIZ001",
"questions": [
{
"questionLabel": "Quelle longueur faisait l’aqueduc du Gier pour acheminer l’eau sur Lyon à l’époque romaine ?",
"answers": [
{ "answerLabel": "86 km", "isTrue": true },
{
"answerLabel": "78 km",
"isTrue": false
},
{
"answerLabel": "56 km",
"isTrue": false
}
],
"explanation": "L’aqueduc du Gier est un des aqueducs antiques de Lyon desservant la ville antique de Lugdunum. Avec ses 86 km il est le plus long des quatre aqueducs ayant alimenté la ville en eau, et celui dont les structures sont le mieux conservées. Il doit son nom au fait qu'il puise aux sources du Gier, affluent du Rhône",
"source": "string"
},
{
"questionLabel": "Quelle type de pompes étaient utilisées à l'usine des eaux de Caluire jusqu'en 1910 ?",
"answers": [
{
"answerLabel": "Pompe à cordes",
"isTrue": true
},
{
"answerLabel": "Pompe de Cornouailles",
"isTrue": false
},
{
"answerLabel": "Pompe à air",
"isTrue": false
}
],
"explanation": "Mise en fonctionnement en 1856, 3 pompes à vapeur dites de Cornouailles produisent quelque 20 000 m3 d'eau par jour. Ces pompes mesurent 20 m de haut et 13 m de large pour un poids de 200 tonnes. Leur balancier de 35 tonnes s'actionne toutes les 6 secondes, permettant ainsi l'envoi de 600 m3 d'eau par heure.",
"source": "string"
},
{
"questionLabel": "Quelle est le nom du principal champ de captage d’eau potable de la Métropole ?",
"answers": [
{ "answerLabel": "Crémieux", "isTrue": false },
{
"answerLabel": "Crépieux-Charmy",
"isTrue": true
},
{
"answerLabel": "Charly",
"isTrue": false
}
],
"explanation": "Crépieux-Charmy est le principal champ captant de la Métropole de Lyon",
"source": "string"
},
{
"questionLabel": "De quoi les nuages sont-ils constitués ?",
"answers": [
{ "answerLabel": "Vapeur d'eau", "isTrue": false },
{
"answerLabel": "Fumée",
"isTrue": false
},
{
"answerLabel": "Gouttelettes d'eau et cristaux de glace",
"isTrue": true
}
],
"explanation": "Les nuages sont constitués de gouttelettes d'eau et parfois aussi de cristaux de glace",
"source": "string"
}
],
"customQuestion": {
"questionLabel": "Quel jour ai-je le plus consommé la semaine dernière ?",
"type": 0,
"timeStep": 20,
"interval": 30,
"period": {}
}
}
```
## Duel
### Description
This doctype is used to store all duels.
### Doctype
**`com.grandlyon.ecolyo.duel`**
### Structure
| Field | Type | Description |
| ----------- | -------- | -------------------------------------- |
| \_id | string | duel id - respect the format _DUEL00X_ |
| title | string | title of the duel |
| description | string | description of the duel |
| duration | Duration | Luxon Duration of the duel |
### Example
```
{
"_id": "DUEL001",
"title": "Nicolas Hublot",
"description": "Je parie un ours polaire que vous ne pouvez pas consommer moins que #CONSUMPTION € en 1 semaine",
"duration": { "days": 7 }
}
```
docs/img/challengeFlow.png

120 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment