Skip to content
Snippets Groups Projects
challenge.md 12.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Bastien DUMONT's avatar
    Bastien DUMONT committed
    # Challenge
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    This section explain all the functionalities in the challenge part
    
    A quiz includes 4 basic questions and one custom question.
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    ### Process
    
    Questions and answers are generated in random order.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    At the beginning of the quiz, the user have to select an answer and click validate.
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    Then, he sees the right answer and a modal with the explanation. After this modal, he goes to the next question.
    
    Depending on the answer, the question result state is set either to correct or incorrect.
    If it is a right answer, the quiz result is incremented by one.
    
    A user can stop during a quiz and picks up where he left off. To define where the user left off, we have to check if at least one of the question result status is unlocked.
    
    Once the custom question is answered, the quiz state is set to done. Then, the user sees his result and his earned stars. He can also retry or go back to the challenge page.
    
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    ### Basic Question
    
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    All basics Questions are created in the quizEntity.json. We have to add :
    
    
    | Field         | Description                              |
    | ------------- | ---------------------------------------- |
    | questionLabel | Label of the question                    |
    | answers       | Array of 3 answers (answerLabel, isTrue) |
    | description   | Explains the question                    |
    | source        | Source of the explanation                |
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    
    ### Custom Question
    
    
    At the end of every quiz, we're creating a custom question.
    
    Yoan VALLET's avatar
    Yoan VALLET committed
    Here are the fields used to create a custom question
    
    | Field       | Type               | Description                                                                                                                                                                                                                                                                                                                                                                          |
    | ----------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    | type        | CustomQuestionType | Type of custom question: DATE or MAXLOAD or AVERAGE.                                                                                                                                                                                                                                                                                                                                 |
    
    | timeStep    | TimeStep           | Time step of the result value (DAY / WEEK / MONTH / YEAR). For MAXLOAD or AVERAGE type, it represents daily / weekly / monthly / yearly average.                                                                                                                                                                                                                                     |
    | interval    | TimeStep           | Interval in which the data will be searched (DAY / WEEK / MONTH / YEAR)                                                                                                                                                                                                                                                                                                              |
    | period      | CustomPeriod       | Case day / month / year:<br/>Use to define a specific period for the interval { day? / month? / year? }. <br/>Case weekday:<br/>Only usable with AVERAGE type and DAY timestep: Allow to specify a weekday on which average is made. If used with another type, period will not be taken into account.<br/>If not assigned the period will be the last interval (example: last week) |
    | singleFluid | boolean            | Indicate if all connected fluid should be taken into account.<br/>If set to true only the first connected fluid will be taken into account in this order: electricity, gas, water. #unit and #fluid in the question label will be replace by the unit and the name of the fluid                                                                                                      |
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    | result      | UserQuizState      | Indicate the state of the custom question (UNLOCKED, CORRECT, INCORRECT)                                                                                                                                                                                                                                                                                                             |
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    Calculation of custom question is done by combination of all parameters:
    
    #### Type DATE
    
    - If _period_ is empty.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      Retrieve the **date** of day/month/year (define by _timeStep_) from the last week, month, year (define by _interval_), if there is no data in this interval, then it will go back to a previous interval, up to a maximum of 6 months
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: What day did I consumme the most on the last week ?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.DATA
    timeStep = TimeStep.DAY
    interval = TimeStep.WEEK
    period = {}
    singleFluid = false
    ```
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: What day did I consumme the most #fluid in #unit on the last week ?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.DATA
    timeStep = TimeStep.DAY
    interval = TimeStep.WEEK
    period = {}
    singleFluid = true
    ```
    
    - If _period_ is not empty
    
      Retrieve the **date** of day/month/year (define by _timeStep_) from a week, month, year (define by _interval_) of _period_
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: What month did I consumme the most on year 2020 ?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.DATA
    timeStep = TimeStep.MONTH
    interval = TimeStep.YEAR
    period = { year: 2020 }
    singleFluid = false
    ```
    
    #### Type MAXLOAD
    
    - If _period_ is empty
    
    Retrieve the **maxload** value of day/month/year (define by _timeStep_) from the last week, month, year (define by _interval_).
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: Which is your daily max consumption on the last week ?
    
    type = CustomQuestionType.MAXLOAD
    
    timeStep = TimeStep.DAY
    interval = TimeStep.WEEK
    period = {}
    
    singleFluid = false
    ```
    
    - If _period_ is not empty
    
    Retrieve the **maxload** value of day/month/year (define by _timeStep_) from a week, month, year (define by _interval_) of _period_
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: Which is your daily max consumption on january 2020 ?
    
    type = CustomQuestionType.MAXLOAD
    
    timeStep = TimeStep.DAY
    interval = TimeStep.MONTH
    
    period = { month: 1, year: 2020 }
    singleFluid = false
    ```
    
    #### Type AVERAGE
    
    - If _period_ is empty
    
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    Retrieve the **average** of day/month/year (define by _timeStep_) from the last week, month, year (define by _interval_).
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: Which is your daily average consumption on last week ?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.AVERAGE
    timeStep = TimeStep.DAY
    interval = TimeStep.WEEK
    period = {}
    singleFluid = false
    ```
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    - If _period_ is not empty
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    Retrieve the **average** of day/month/year (define by _timeStep_) from a week, month, year (define by _interval_) of _period_
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: Which is your daily average consumption on january 2020 ?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.AVERAGE
    timeStep = TimeStep.DAY
    interval = TimeStep.MONTH
    period = { month: 1, year: 2020 }
    singleFluid = false
    ```
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    - If _period_ is weekday
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    Retrieve the **average** of the _weekday_ from a week, month, year (define by _interval_).
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```js
    // example: Which is your daily average consumption on wednesdays of last month?
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    type = CustomQuestionType.AVERAGE
    timeStep = TimeStep.DAY
    interval = TimeStep.MONTH
    period = { weekday: 3 }
    singleFluid = false
    ```
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    #### Wrong answers
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    After defining the right answer, two random answers are generated depending of the custom question type:
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    - type DATE
    
    Two dates is generated one, a day before the correct date and the other, a day after.
    
    - type MAXLOAD or AVERAGE
    
    Two random value is generated by applying a coefficient based on the correct answer.
    This coefficient is randomly included between 0.7 and 0.9 (for the first value) or between 1.1 and 1.3 (for the second value)
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    ## Exploration
    
    Exploration is a feature where the user has to do an action in order to help him discover all features from ecolyo.
    They are 4 types of actions:
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    - DECLARATIVE : The user has to do something outside of the app => No way for the app to know if the user did it so we trust him.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    - ACTION : Action within the app. When the user finishes he gets a notification.
    
    - CONSUMPTION : He has to do something in his consumption view.
    - ECOGESTURE : He needs to look at a specific Ecogesture.
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    In order to check if an exploration (which is not declarative) is done, a hook called userExploration is used.It is called on component that has to check if an exploration is done.
    
    This hook called exploration service to check exploration by passing two parameters (the current challenge and the user exploration id associated with the exploration id of the current challenge). This check is done only if:
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    - There is a current challenge
    - exploration.id of the current challenge is equal to the user exploration id
    - exploration.state is ONGOING
    
    Depends on the type of an exploration, either the exploration remains in progress until it is fully done or it ends.
    
    
    When the user finish the exploration, he gets a success message and five more stars are added to his challenge progression.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    ## Action
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    Action is a feature which in the user has to apply an ecogesture for a given duration in order to reduce his consumption. An action refers to the model **UserAction** in the app, and is an extension of an ecogesture to which we add an _startDate_ and a _userActionState_, allowing user to manage the action state depending on user's progress.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```ts
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    UserAction {
      ecogesture: Ecogesture | null
      state: UserActionState
      startDate: DateTime | null
    }
    ```
    
    Unlike the exploration, duel and quiz, there is no relationship for an action in the **ChallengeEntity** model, given that the action is picked by the user. So once it is picked, it is directly stored in the current **UserChallenge**.
    
    When a user launches an action, there is several possible cases :
    
    ### The user has not completed his consumption profile
    
    If the user's profile has never been completed, the application will purpose him the default action list which is defined in the action service. The first one of this list will be shown at first, and if the user wants to pick another one, he'll have the choice between the three ecogestures of the default list.
    
    ### The user has completed his consumption profile
    
    If the user has completed his profile, the application will purpose him a list of three custom ecogestures. The list is built the following way :
    
    1. First we look for the action that haven't been done yet
    2. We pick only the actions that are available for the user's connected fluids
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    3. We pick actions that are applicable during the current season. At this moment, if the list is smaller than 3, we complete it with actions whose value for property **Season** is _NONE_
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    4. If the list is still smaller than 3 after this, we complete with default actions (This case is rare)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    5. Finally, we sort the list of action by efficiency and then difficulty. We put the most efficient actions and with the lowest difficulty in first.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    
    At any moment of an action, a user can consult his progress through a clock icon and the ending date of his action.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    The accomplishment of an action is only conditioned by the duration. Once the user completes an action, he'll see a notification on the app and then win his five stars when he comes back to the action screen.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    ### 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 time if the ones before got missing values.  
    
    We also define a threshold for a maximum old period
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! note "6 months for the moment - hard coded."
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    If the threshold 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.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    ### On going
    
    Every time the user goes into the duel mode, we are checking if the duel is finished.
    if we have retrieved all data to calculate the user consumption on the duel duration, the duel is done.
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    !!! info "In order to not block the user if a value is missing, we are also setting the duel as done when we reach the startDate + delay in day to retrieve the data (based on the fluid) + 1 day. In this case the user consumption is done on known values."
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    ### On finish
    
    Once the state of the duel is set to DONE, we save the user result and determine if he wins (userConsumption < threshold of the reference period) or if he loses. Then the user sees his earned badge.
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
    ## 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.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    For more precision about the data management system you can refer the picture in the [Initialization section](./initialization.md)