import { Client } from 'cozy-client' import _ from 'lodash' import { DateTime } from 'luxon' import { FluidType } from 'enum/fluid.enum' import { getPercentage, sum } from 'utils/math' import { getDoctype } from 'utils/utils' export type ProcessedData = { consumptionValue: number weeklyCompareValue: number euclideanComparator: string } export default class FluidService { public client: Client constructor(client: Client) { this.client = client } private getTimeQueryPredicate( startingdateTime: DateTime, endingdateTime: DateTime ) { return { year: { $lte: Math.max(startingdateTime.year, endingdateTime.year), $gte: Math.min(startingdateTime.year, endingdateTime.year), }, month: { $lte: Math.max(startingdateTime.month, endingdateTime.month), $gte: Math.min(startingdateTime.month, endingdateTime.month), }, day: { $lte: Math.max(startingdateTime.day, endingdateTime.day), $gte: Math.min(startingdateTime.day, endingdateTime.day), }, } } /** * Query last 2 week data for grdf energy data */ public getLastTwoWeeks(fluid: FluidType) { //const now = DateTime.local(2018, 4, 1) const now = DateTime.local() const twoWeekBefore = now.minus({ week: 2, }) return this.client.query( this.getClientQuery( getDoctype(fluid), now, twoWeekBefore, ['year', 'month', 'day'], 14 ) ) } /** * Build client query * @param doctype doctype name * @param startingTime start date for query * @param endingTime end date for query * @param indexFields fields needed to be indexed * @param recordsNumber number or return values */ private getClientQuery( doctype: string, startingTime: DateTime, endingTime: DateTime, indexFields: string[], recordsNumber: number ) { return this.client .find(doctype) .where(this.getTimeQueryPredicate(startingTime, endingTime)) .indexFields(indexFields) .limitBy(recordsNumber) } /** * Wrap up data needed for electrical indicators * @param {array} toBeProcessedData * @return {object} {consumptionValue: number, weeklyCompareValue: number, euclideanComparator: string} */ public processElectricityData(toBeProcessedData: []) { const consumptionValue = sum( _.slice(_.map(toBeProcessedData, 'load'), 7, 14) ) const weeklyCompareValue = getPercentage( _.slice(_.map(toBeProcessedData, 'load'), 7, 14), _.slice(_.map(toBeProcessedData, 'load'), 0, 7) ) const euclideanComparator = this.getRelevantMetric( FluidType.ELECTRICITY, consumptionValue ) return { consumptionValue: consumptionValue, weeklyCompareValue: weeklyCompareValue, euclideanComparator: euclideanComparator, } } /** * Wrap up data needed for gas indicators * @param {array} toBeProcessedData * @return {object} {consumptionValue: number, weeklyCompareValue: number, euclideanComparator: string} */ public processGasData(toBeProcessedData: []) { // Remove last element in order to have pair number of value. toBeProcessedData.pop() const consumptionValue = sum( _.slice(_.map(toBeProcessedData, 'load'), 0, 7) ) const weeklyCompareValue = getPercentage( _.slice(_.map(toBeProcessedData, 'load'), 0, 7), _.slice(_.map(toBeProcessedData, 'load'), 7, 14) ) const euclideanComparator = this.getRelevantMetric( FluidType.GAS, consumptionValue ) return { consumptionValue: consumptionValue, weeklyCompareValue: weeklyCompareValue, euclideanComparator: euclideanComparator, } } /** * Wrap up data needed for water indicators * @param {array} toBeProcessedData * @return {object} {consumptionValue: number, weeklyCompareValue: number, euclideanComparator: string} */ public processWaterData(toBeProcessedData: []) { const consumptionValue = sum( _.slice(_.map(toBeProcessedData, 'load'), 0, 7) ) const weeklyCompareValue = getPercentage( _.slice(_.map(toBeProcessedData, 'load'), 0, 7), _.slice(_.map(toBeProcessedData, 'load'), 7, 14) ) const euclideanComparator = this.getRelevantMetric( FluidType.WATER, consumptionValue ) return { consumptionValue: consumptionValue, weeklyCompareValue: weeklyCompareValue, euclideanComparator: euclideanComparator, } } /** * Return a relevant metric string according to a fluid type and a value * @param {FluidType} fluid * @param {number} value * @return {string} relevantValue */ public getRelevantMetric(fluid: FluidType, value: number) { //TODO: When data is ready get it from db or locales switch (fluid) { case FluidType.ELECTRICITY: if (value > 100) { return "Vous avez consommé un max d'ampoules !" } else { return 'Une console de jeu fonctionnant 2 h par jour consomme 1,75 kWh en 1 semaine' } case FluidType.GAS: return 'Ca fait pas un peu trop de gas' case FluidType.WATER: return '3 piscines du rhône' default: return 'Pas de comparaison trouvée' } } }