76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
import * as functions from 'firebase-functions'
|
|
import * as admin from 'firebase-admin'
|
|
import { uniq } from 'lodash'
|
|
import { Bet } from '../../common/bet'
|
|
import { Contract } from '../../common/contract'
|
|
import { log } from './utils'
|
|
import { removeUndefinedProps } from '../../common/util/object'
|
|
import { DAY_MS, HOUR_MS } from '../../common/util/time'
|
|
|
|
export const scoreContracts = functions
|
|
.runWith({ memory: '4GB', timeoutSeconds: 540 })
|
|
.pubsub.schedule('every 1 hours')
|
|
.onRun(async () => {
|
|
await scoreContractsInternal()
|
|
})
|
|
const firestore = admin.firestore()
|
|
|
|
async function scoreContractsInternal() {
|
|
const now = Date.now()
|
|
const hourAgo = now - HOUR_MS
|
|
const dayAgo = now - DAY_MS
|
|
const threeDaysAgo = now - DAY_MS * 3
|
|
const activeContractsSnap = await firestore
|
|
.collection('contracts')
|
|
.where('lastUpdatedTime', '>', hourAgo)
|
|
.get()
|
|
const activeContracts = activeContractsSnap.docs.map(
|
|
(doc) => doc.data() as Contract
|
|
)
|
|
// We have to downgrade previously active contracts to allow the new ones to bubble up
|
|
const previouslyActiveContractsSnap = await firestore
|
|
.collection('contracts')
|
|
.where('popularityScore', '>', 0)
|
|
.get()
|
|
const activeContractIds = activeContracts.map((c) => c.id)
|
|
const previouslyActiveContracts = previouslyActiveContractsSnap.docs
|
|
.map((doc) => doc.data() as Contract)
|
|
.filter((c) => !activeContractIds.includes(c.id))
|
|
|
|
const contracts = activeContracts.concat(previouslyActiveContracts)
|
|
log(`Found ${contracts.length} contracts to score`)
|
|
|
|
for (const contract of contracts) {
|
|
const bets = await firestore
|
|
.collection(`contracts/${contract.id}/bets`)
|
|
.where('createdTime', '>', threeDaysAgo)
|
|
.get()
|
|
const bettors = bets.docs
|
|
.map((doc) => doc.data() as Bet)
|
|
.map((bet) => bet.userId)
|
|
const popularityScore = uniq(bettors).length
|
|
|
|
const wasCreatedToday = contract.createdTime > dayAgo
|
|
|
|
let dailyScore: number | undefined
|
|
if (
|
|
contract.outcomeType === 'BINARY' &&
|
|
contract.mechanism === 'cpmm-1' &&
|
|
!wasCreatedToday
|
|
) {
|
|
const percentChange = Math.abs(contract.probChanges.day)
|
|
dailyScore = popularityScore * percentChange
|
|
}
|
|
|
|
if (
|
|
contract.popularityScore !== popularityScore ||
|
|
contract.dailyScore !== dailyScore
|
|
) {
|
|
await firestore
|
|
.collection('contracts')
|
|
.doc(contract.id)
|
|
.update(removeUndefinedProps({ popularityScore, dailyScore }))
|
|
}
|
|
}
|
|
}
|