Skip to content
Snippets Groups Projects
initialization.md 6.22 KiB
Newer Older
  • Learn to ignore specific revisions
  • Bastien DUMONT's avatar
    Bastien DUMONT committed
    # Initialization
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    This section explains how to handle data storage.
    
    We handle data storage according to the following process :
    
    
    The folder `/src/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.
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    ## 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": "",
    
        "quizHash": "",
        "explorationHash": "",
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
        "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.
    
    In order to handle this process, each entity that is likely to change has a function that takes the current hash in entry, and execute the following process :
    
    - creates a hash from the related entity file (for example **EcogestureData.json**)
    - get the entities from the database
    - if there is no entity stored, populates the related doctype (for this example **ECOGESTURE_DOCTYPE**) for each item stored in the entity file
    - compare the number of entries created in the doctype with the number of item in the entity file
    - if the previous hash and the new hash are different, delete all entries in the doctype and populates with the items stored in the entity file
    
    Functions used to init or update the hash :
    
    | Function                            |
    | ----------------------------------- |
    | initEcogesture(hash: string)        |
    | initChallengeEntity(hash: string)   |
    | initDuelEntity(hash: string)        |
    | initQuizEntity(hash: string)        |
    | initExplorationEntity(hash: string) |
    
    
    :::info Exception for ecogestures
    
    When we update the ecogesture list in **ecogestureData.json**, we also get the previous existing list to transfer the ecogesture status (doing and/or objective) to the updated list.
    
    :::
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    ### 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.
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    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.
    
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    Using this 2 structures allows us to keep user's data when we'll update the application, by editing just the entities.
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    ### 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.
    
    
    Relations are set as *HasOne* relationships for **Quiz** and **Duel** because there is only one quiz and one duel for Challenge. Thus, we use a *HasMany* relation for the **Exploration**, because one challenge can have several exploration in order the handle the specific cases of fluid-based explorations.
    
    
    You can see more about relationships on [cozy documentation](https://docs.cozy.io/en/cozy-doctypes/docs/io.cozy.apps.suggestions/#relationships).
    
    HAUTBOIS Aurelie's avatar
    HAUTBOIS Aurelie committed
    
    ```json
    "relationships": {
          "quiz": {
            "data": { "_id": "QUIZ001", "_type": "com.grandlyon.ecolyo.quiz" }
          },
          "duel": {
            "data": { "_id": "DUEL001", "_type": "com.grandlyon.ecolyo.duel" }
    
          },
          "exploration": {
            "data": [
              {
                "_id": "EXPLORATION001",
                "_type": "com.grandlyon.ecolyo.exploration"
              }
            ]
    
    
    ### UserData creation
    
    
    We create a userData and store it in the CouchDB under the doctype userData name '**com.grandlyon.ecolyo.userDataName'.** During this process, the objects related to the dataEntity will be be converted to an user version which contains information about the user(example: user progress, the fluids connected and so on).
    
    To illustrate this, let's show an example of the conversion of duelEntity to UserDuel :
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```ts
    
    DuelEntity {
      id: string
      title: string
      description: string
      duration: Duration
    }
    ```
    
    Becomes :
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```ts
    
    UserDuel {
      id: string
      title: string
      description: string
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      duration: Duration
    
      threshold: number
      state: UserDuelState
      startDate: DateTime | null
      fluidTypes: FluidType[]
      userConsumption: number
    }
    ```
    
    
    Since we use the Luxon library for DateTimes, we need to have an intermediate interface for the UserDuel. Indeed, the database doesn't know the DateTime type, so when we query a UserDuel, its **startDate** property is a *string* and not a *DateTime*.
    
    
    The solve this and avoid Typescript errors, we created the following interface :
    
    ```jsx
    UserDuelEntity {
    
      id: string
      title: string
      description: string
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      duration: Duration
    
      threshold: number
      state: UserDuelState
      startDate: string | null
      fluidTypes: FluidType[]
      userConsumption: number
    }
    ```
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    ### Data management schema
    
    
    ![Data Scheme](/img/challengeFlow.png)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    The initialization process displays progression steps in the splash screen so the user can see what is happening while it is loading. Each initialization function set an error if it fails, which is shown on the Splash error screen.
    
    
    Available loading steps are the followings :
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```ts
    
      MIGRATION = 0,
      CONSENT = 1,
      PROFILE = 2,
      ECOGESTURE = 3,
      CHALLENGES = 4,
      PRICES = 5,
      CONSOS = 6,
    ```
    
    Possible errors are the followings :
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    ```ts
    
      MIGRATION_ERROR = 'migration_error',
      CONSENT_ERROR = 'consent_error',
      PROFILE_ERROR = 'profile_error',
      PROFILETYPE_ERROR = 'profileType_error',
      ECOGESTURE_ERROR = 'ecogesture_error',
      CHALLENGES_ERROR = 'challenges_error',
      ANALYSIS_ERROR = 'analysis_error',
      INDEX_ERROR = 'index_error',
      PRICES_ERROR = 'prices_error',
      CONSOS_ERROR = 'consos_error',
      PARTNERS_ERROR = 'partners_error',
      UNKNOWN_ERROR = 'unknown_error',
    ```