Skip to content
Snippets Groups Projects
initDataManagerService.ts 14.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Hugo NOUTS's avatar
    Hugo NOUTS committed
    import { Client } from 'cozy-client'
    import {
      CHALLENGETYPE_DOCTYPE,
      ECOGESTURE_DOCTYPE,
      USERCHALLENGE_DOCTYPE,
      USERPROFILE_DOCTYPE,
      EGL_DAY_DOCTYPE,
      EGL_MONTH_DOCTYPE,
      EGL_YEAR_DOCTYPE,
      ENEDIS_DAY_DOCTYPE,
      ENEDIS_MINUTE_DOCTYPE,
      ENEDIS_MONTH_DOCTYPE,
      ENEDIS_YEAR_DOCTYPE,
      GRDF_DAY_DOCTYPE,
      GRDF_HOUR_DOCTYPE,
      GRDF_MONTH_DOCTYPE,
      GRDF_YEAR_DOCTYPE,
    } from 'doctypes'
    
    import ChallengeDataManager from 'services/challengeDataManagerService'
    import challengeTypeData from 'db/challengeTypeData.json'
    import userChallengeData from 'db/userChallengeData.json'
    import EcogestureDataManager from 'services/ecogestureDataManagerService'
    import ecogestureData from 'db/ecogestureData.json'
    import UserProfileDataManager from 'services/userProfileDataManagerService'
    import userProfileData from 'db/userProfileData.json'
    import KonnectorStatusService from 'services/konnectorStatusService'
    
    import KonnectorService from 'services/konnectorService'
    import { AccountService } from 'services/accountService'
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
    
    import { hashFile } from 'utils/hash'
    import {
      UserProfile,
      TypeChallenge,
      UserChallenge,
    } from 'services/dataChallengeContracts'
    import { FluidType } from 'enum/fluid.enum'
    import { DateTime } from 'luxon'
    
    export default class InitDataManager {
      private readonly _client: Client
    
      constructor(_client: Client) {
        this._client = _client
      }
    
      public async checkChallengeType(hash: string): Promise<boolean> {
        const hashChanllengeType = hashFile(challengeTypeData)
        const cdm = new ChallengeDataManager(this._client)
        const updm = new UserProfileDataManager(this._client)
    
        // Populate data if none challengeType exists
        const loadedChallengeTypes = await cdm.getAllChallengeTypeEntities()
        if (
          !loadedChallengeTypes ||
          (loadedChallengeTypes && loadedChallengeTypes.length === 0)
        ) {
          // Populate the doctype with data
          try {
            for (let i = 0; i <= challengeTypeData.length - 1; i++) {
              const result = await this._client.create(
                CHALLENGETYPE_DOCTYPE,
                challengeTypeData[i]
              )
              if (!result) {
                return false
              }
            }
            // Check of created document
            const checkCount = await cdm.getAllChallengeTypeEntities()
            if (
              !checkCount ||
              (checkCount && checkCount.length !== challengeTypeData.length)
            ) {
              return false
            }
            // Update userProfil with the hash
            const updatedUserProfil = await updm.updateUserProfile({
              challengeTypeHash: hashChanllengeType,
            })
            if (!updatedUserProfil) {
              return false
            }
          } catch (error) {
            console.log('Context error: ', error)
            return false
          }
          return true
        }
    
        // Update if the hash is not the same as the one from userprofile
        if (hash !== hashChanllengeType) {
          // Update the doctype
          try {
            // Deletion of all documents
            const resultDeletion = await cdm.deleteAllChallengeTypeEntities()
            if (!resultDeletion) {
              return false
            }
            // Population with the data
            const resultPopulation = await Promise.all(
              challengeTypeData.map(async challengeType => {
                await this._client.create(CHALLENGETYPE_DOCTYPE, challengeType)
              })
            )
            if (!resultPopulation) {
              return false
            }
            // Check of created document
            const checkCount = await cdm.getAllChallengeTypeEntities()
            if (
              !checkCount ||
              (checkCount && checkCount.length !== challengeTypeData.length)
            ) {
              return false
            }
            // Update userProfil with the hash
            const updatedUserProfil = await updm.updateUserProfile({
              challengeTypeHash: hashChanllengeType,
            })
            if (!updatedUserProfil) {
              return false
            }
          } catch (error) {
            console.log('Context error: ', error)
            return false
          }
          return true
        } else {
          // Doctype already up to date
          return true
        }
      }
    
      public async checkEcogesture(hash: string): Promise<boolean> {
        const hashEcogestureType = hashFile(ecogestureData)
        const edm = new EcogestureDataManager(this._client)
        const updm = new UserProfileDataManager(this._client)
    
        // Populate data if none ecogesture exists
        const loadedEcogestures = await edm.getAllEcogestures()
        if (
          !loadedEcogestures ||
          (loadedEcogestures && loadedEcogestures.length === 0)
        ) {
          // Populate the doctype with data
          try {
            for (let i = 0; i <= ecogestureData.length - 1; i++) {
              const result = await this._client.create(
                ECOGESTURE_DOCTYPE,
                ecogestureData[i]
              )
              if (!result) {
                return false
              }
            }
    
            // Check of created document based on count
            const checkCount = await edm.getAllEcogestures()
            if (
              !checkCount ||
              (checkCount && checkCount.length !== ecogestureData.length)
            ) {
              return false
            }
            // Update userProfil with the hash
            const updatedUserProfil = await updm.updateUserProfile({
              ecogestureHash: hashEcogestureType,
            })
            if (!updatedUserProfil) {
              return false
            }
          } catch (error) {
            console.log('Context error: ', error)
            return false
          }
          return true
        }
    
        // Update if the hash is not the same as the one from userprofile
        if (hash !== hashEcogestureType) {
          // Update the doctype
          try {
            // Deletion of all documents
            const resultDeletion = await edm.deleteAllEcogestures()
            if (!resultDeletion) {
              return false
            }
            // Population with the data
            const resultPopulation = await Promise.all(
              ecogestureData.map(async ecogesture => {
                await this._client.create(ECOGESTURE_DOCTYPE, ecogesture)
              })
            )
            if (!resultPopulation) {
              return false
            }
            // Check of created document based on count
            const checkCount = await edm.getAllEcogestures()
            if (
              !checkCount ||
              (checkCount && checkCount.length !== ecogestureData.length)
            ) {
              return false
            }
            // Update userProfil with the hash
            const updatedUserProfil = await updm.updateUserProfile({
              ecogestureHash: hashEcogestureType,
            })
            if (!updatedUserProfil) {
              return false
            }
          } catch (error) {
            console.log('Context error: ', error)
            return false
          }
          return true
        } else {
          // Doctype already up to date
          return true
        }
      }
    
      /*
       * Check if userChallenge exist
       * If not, the userChallenge is created
       * sucess return: true
       * failure return: false
       */
      public async checkUserChallenge(): Promise<boolean> {
        const cdm = new ChallengeDataManager(this._client)
        const loadedUserChallenge = await cdm.getAllUserChallengeEntities()
        if (
          !loadedUserChallenge ||
          (loadedUserChallenge && loadedUserChallenge.length === 0)
        ) {
          try {
            // Population with the data
            await this._client.create(USERCHALLENGE_DOCTYPE, userChallengeData[0])
            // Check of created document
            const checkUserChallenge = await cdm.getAllUserChallengeEntities()
            if (!checkUserChallenge) {
              return false
            }
            return true
          } catch (error) {
            console.log('Context error: ', error)
            return false
          }
        } else {
          return true
        }
      }
    
      /*
       * Check if UserProfil exist
       * If not, the UserProfil is created
       * sucess return: userProfil
       * failure return: null
       */
      public async checkUserProfile(): Promise<UserProfile | null> {
        const updm = new UserProfileDataManager(this._client)
        const loadedUserProfile = await updm.getUserProfile()
        if (!loadedUserProfile) {
          try {
            // Population with the data
            await this._client.create(USERPROFILE_DOCTYPE, userProfileData[0])
            // Check of created document
            const checkUserProfile = await updm.getUserProfile()
            return checkUserProfile
          } catch (error) {
            console.log('Context error: ', error)
            return null
          }
        } else {
          return loadedUserProfile
        }
      }
    
      /*
       * Call each check function to init data
       * sucess return: true
       * failure return: false or null
       */
      public async initData(): Promise<boolean | null> {
        try {
          const resultUserProfile = await this.checkUserProfile()
          if (!resultUserProfile) {
            return false
          } else {
            console.log(
              '%c Context: UserProfile loaded ',
              'background: #222; color: white'
            )
          }
          const resultChallengeType = await this.checkChallengeType(
            resultUserProfile.challengeTypeHash
          )
          if (!resultChallengeType) {
            return false
          } else {
            console.log(
              '%c Context: ChallengeType loaded ',
              'background: #222; color: white'
            )
          }
          const resultEcogesture = await this.checkEcogesture(
            resultUserProfile.ecogestureHash
          )
          if (!resultEcogesture) {
            return false
          } else {
            console.log(
              '%c Context: Ecogesture loaded ',
              'background: #222; color: white'
            )
          }
          const resultUserChallenge = await this.checkUserChallenge()
          if (!resultUserChallenge) {
            return false
          } else {
            console.log(
              '%c Context: UserChallenge loaded',
              'background: #222; color: white'
            )
          }
          return true
        } catch (error) {
          console.log('Context error: ', error)
          return null
        }
      }
    
      /*
       * Check if FluidTypes exist
       * sucess return: FluidType[]
       * failure return: null
       */
      public async checkFluidTypes(): Promise<FluidType[] | null> {
        const kss = new KonnectorStatusService(this._client)
        try {
          const fluidtypes = await kss.getKonnectorAccountStatus()
          if (!fluidtypes) {
            return null
          }
          return fluidtypes
        } catch (error) {
          console.log('Context error: ', error)
          return null
        }
      }
    
      /*
       * Call a query with where clause to create the index if not exist
       */
      public async createIndex(doctype: string): Promise<any> {
        return await this._client.query(
          this._client
            .find(doctype)
            .where({
              year: {
                $lte: 9999,
              },
              month: {
                $lte: 12,
              },
              day: {
                $lte: 31,
              },
            })
            .limitBy(1)
        )
      }
    
      /*
       * create index for each Doctype
       * sucess return: true
       * failure return: null
       */
      public async initIndex(): Promise<boolean | null> {
        try {
          await this.createIndex(EGL_DAY_DOCTYPE)
          await this.createIndex(EGL_MONTH_DOCTYPE)
          await this.createIndex(EGL_YEAR_DOCTYPE)
          await this.createIndex(ENEDIS_DAY_DOCTYPE)
          await this.createIndex(ENEDIS_MINUTE_DOCTYPE)
          await this.createIndex(ENEDIS_MONTH_DOCTYPE)
          await this.createIndex(ENEDIS_YEAR_DOCTYPE)
          await this.createIndex(GRDF_DAY_DOCTYPE)
          await this.createIndex(GRDF_HOUR_DOCTYPE)
          await this.createIndex(GRDF_MONTH_DOCTYPE)
          await this.createIndex(GRDF_YEAR_DOCTYPE)
    
          await KonnectorService.createIndexKonnector(this._client)
          await AccountService.createIndexAccount(this._client)
    
    Hugo NOUTS's avatar
    Hugo NOUTS committed
          return true
        } catch (error) {
          console.log('Context error: ', error)
          return null
        }
      }
    
      /*
       * Search for a current challenge
       * and update it if found
       */
      public async checkCurrentChallenge(
        fluidTypes: FluidType[]
      ): Promise<UserChallenge | null> {
        try {
          // get the current challenge
          const cdm = new ChallengeDataManager(this._client)
          const currentChallenge = await cdm.getCurrentChallenge()
          if (!currentChallenge) {
            // No current challenge
            return null
          } else {
            if (
              currentChallenge &&
              currentChallenge.challengeType &&
              currentChallenge.challengeType.type === TypeChallenge.CHALLENGE
            ) {
              // Check if we are in the viewing timezone for current challenge
              const viewingDate = cdm.getViewingDate(currentChallenge, fluidTypes)
              if (DateTime.local() >= viewingDate) {
                if (currentChallenge.maxEnergy === -1) {
                  const maxEnergyResult = await cdm.setMaxEnergy(
                    currentChallenge,
                    this._client,
                    fluidTypes
                  )
                  if (maxEnergyResult > 0) {
                    currentChallenge.maxEnergy = maxEnergyResult
                  }
                }
                const currentEnergyResult = await cdm.setSpentEnergy(
                  currentChallenge,
                  this._client,
                  fluidTypes
                )
                if (currentEnergyResult) {
                  currentChallenge.currentEnergy = currentEnergyResult
                }
              }
            }
            return currentChallenge
          }
        } catch (error) {
          console.log('Context error: ', error)
          throw error
        }
      }
    
      /*
       * If the challenge is over
       * Set the rigth badge and return true
       * else return false
       */
      public async isCurrentChallengeOver(
        challenge: UserChallenge,
        fluidTypes: FluidType[]
      ): Promise<boolean> {
        try {
          // get the current challenge
          if (!challenge) {
            // No current challenge
            return false
          } else {
            const cdm = new ChallengeDataManager(this._client)
            const typeChallenge = challenge.challengeType
              ? challenge.challengeType.type
              : 0
            const isOver = await cdm.isChallengeOverByDate(
              challenge.endingDate,
              fluidTypes,
              typeChallenge
            )
            if (isOver) {
              await cdm.setTheRightBadge(challenge)
              return true
            } else {
              return false
            }
          }
        } catch (error) {
          console.log('Context error: ', error)
          return false
        }
      }
    
      public async checkAchievement(id: string): Promise<UserChallenge | null> {
        const cdm = new ChallengeDataManager(this._client)
        return await cdm.checkAchievement(id)
      }
    }