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' 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) 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) } }