From 00de66cd7910205651e8c7a94f7b154fd79f8683 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Fri, 2 Sep 2022 15:59:32 -0500 Subject: [PATCH] Leaderboard calc: update profit even when portfolio didn't change (#845) * Leaderboard calc: remove didProfitChange optimization that was incorrect * Put back didPortfolioChange for deciding whether to create new history doc. --- functions/src/update-metrics.ts | 60 +++++++++++++++------------------ 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/functions/src/update-metrics.ts b/functions/src/update-metrics.ts index 9ef3fb10..305cd80c 100644 --- a/functions/src/update-metrics.ts +++ b/functions/src/update-metrics.ts @@ -1,13 +1,12 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' -import { groupBy, isEmpty, keyBy, sum, sumBy } from 'lodash' +import { groupBy, isEmpty, keyBy, last, sortBy, sum, sumBy } from 'lodash' import { getValues, log, logMemory, writeAsync } from './utils' import { Bet } from '../../common/bet' import { Contract } from '../../common/contract' import { PortfolioMetrics, User } from '../../common/user' import { calculatePayout } from '../../common/calculate' import { DAY_MS } from '../../common/util/time' -import { last } from 'lodash' import { getLoanUpdates } from '../../common/loans' const firestore = admin.firestore() @@ -88,23 +87,20 @@ export const updateMetricsCore = async () => { currentBets ) const lastPortfolio = last(portfolioHistory) - const didProfitChange = + const didPortfolioChange = lastPortfolio === undefined || lastPortfolio.balance !== newPortfolio.balance || lastPortfolio.totalDeposits !== newPortfolio.totalDeposits || lastPortfolio.investmentValue !== newPortfolio.investmentValue - const newProfit = calculateNewProfit( - portfolioHistory, - newPortfolio, - didProfitChange - ) + const newProfit = calculateNewProfit(portfolioHistory, newPortfolio) + return { user, newCreatorVolume, newPortfolio, newProfit, - didProfitChange, + didPortfolioChange, } }) @@ -120,16 +116,20 @@ export const updateMetricsCore = async () => { const nextLoanByUser = keyBy(userPayouts, (payout) => payout.user.id) const userUpdates = userMetrics.map( - ({ user, newCreatorVolume, newPortfolio, newProfit, didProfitChange }) => { + ({ + user, + newCreatorVolume, + newPortfolio, + newProfit, + didPortfolioChange, + }) => { const nextLoanCached = nextLoanByUser[user.id]?.payout ?? 0 return { fieldUpdates: { doc: firestore.collection('users').doc(user.id), fields: { creatorVolumeCached: newCreatorVolume, - ...(didProfitChange && { - profitCached: newProfit, - }), + profitCached: newProfit, nextLoanCached, }, }, @@ -140,11 +140,7 @@ export const updateMetricsCore = async () => { .doc(user.id) .collection('portfolioHistory') .doc(), - fields: { - ...(didProfitChange && { - ...newPortfolio, - }), - }, + fields: didPortfolioChange ? newPortfolio : {}, }, } } @@ -171,15 +167,15 @@ const computeVolume = (contractBets: Bet[], since: number) => { const calculateProfitForPeriod = ( startTime: number, - portfolioHistory: PortfolioMetrics[], + descendingPortfolio: PortfolioMetrics[], currentProfit: number ) => { - const startingPortfolio = [...portfolioHistory] - .reverse() // so we search in descending order (most recent first), for efficiency - .find((p) => p.timestamp < startTime) + const startingPortfolio = descendingPortfolio.find( + (p) => p.timestamp < startTime + ) if (startingPortfolio === undefined) { - return 0 + return currentProfit } const startingProfit = calculateTotalProfit(startingPortfolio) @@ -233,28 +229,28 @@ const calculateNewPortfolioMetrics = ( const calculateNewProfit = ( portfolioHistory: PortfolioMetrics[], - newPortfolio: PortfolioMetrics, - didProfitChange: boolean + newPortfolio: PortfolioMetrics ) => { - if (!didProfitChange) { - return {} // early return for performance - } - const allTimeProfit = calculateTotalProfit(newPortfolio) + const descendingPortfolio = sortBy( + portfolioHistory, + (p) => p.timestamp + ).reverse() + const newProfit = { daily: calculateProfitForPeriod( Date.now() - 1 * DAY_MS, - portfolioHistory, + descendingPortfolio, allTimeProfit ), weekly: calculateProfitForPeriod( Date.now() - 7 * DAY_MS, - portfolioHistory, + descendingPortfolio, allTimeProfit ), monthly: calculateProfitForPeriod( Date.now() - 30 * DAY_MS, - portfolioHistory, + descendingPortfolio, allTimeProfit ), allTime: allTimeProfit,