Recommend contracts you haven't bet on
This commit is contained in:
parent
1369f3b967
commit
c7452796f0
|
@ -13,7 +13,7 @@ import {
|
||||||
updateDoc,
|
updateDoc,
|
||||||
where,
|
where,
|
||||||
} from 'firebase/firestore'
|
} from 'firebase/firestore'
|
||||||
import { sortBy, sum, uniqBy } from 'lodash'
|
import { partition, sortBy, sum, uniqBy } from 'lodash'
|
||||||
|
|
||||||
import { coll, getValues, listenForValue, listenForValues } from './utils'
|
import { coll, getValues, listenForValue, listenForValues } from './utils'
|
||||||
import { BinaryContract, Contract } from 'common/contract'
|
import { BinaryContract, Contract } from 'common/contract'
|
||||||
|
@ -303,62 +303,63 @@ export async function getClosingSoonContracts() {
|
||||||
return sortBy(chooseRandomSubset(data, 2), (contract) => contract.closeTime)
|
return sortBy(chooseRandomSubset(data, 2), (contract) => contract.closeTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getRandTopCreatorContracts = async (
|
export const getTopCreatorContracts = async (
|
||||||
creatorId: string,
|
creatorId: string,
|
||||||
count: number,
|
count: number
|
||||||
excluding: string[] = []
|
|
||||||
) => {
|
) => {
|
||||||
const creatorContractsQuery = query(
|
const creatorContractsQuery = query(
|
||||||
contracts,
|
contracts,
|
||||||
where('isResolved', '==', false),
|
where('isResolved', '==', false),
|
||||||
where('creatorId', '==', creatorId),
|
where('creatorId', '==', creatorId),
|
||||||
orderBy('popularityScore', 'desc'),
|
orderBy('popularityScore', 'desc'),
|
||||||
limit(count * 2)
|
limit(count)
|
||||||
)
|
)
|
||||||
const data = await getValues<Contract>(creatorContractsQuery)
|
return await getValues<Contract>(creatorContractsQuery)
|
||||||
const open = data
|
|
||||||
.filter((c) => c.closeTime && c.closeTime > Date.now())
|
|
||||||
.filter((c) => !excluding.includes(c.id))
|
|
||||||
|
|
||||||
return chooseRandomSubset(open, count)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getRandTopGroupContracts = async (
|
export const getTopGroupContracts = async (
|
||||||
groupSlug: string,
|
groupSlug: string,
|
||||||
count: number,
|
count: number
|
||||||
excluding: string[] = []
|
|
||||||
) => {
|
) => {
|
||||||
const creatorContractsQuery = query(
|
const creatorContractsQuery = query(
|
||||||
contracts,
|
contracts,
|
||||||
where('groupSlugs', 'array-contains', groupSlug),
|
where('groupSlugs', 'array-contains', groupSlug),
|
||||||
where('isResolved', '==', false),
|
where('isResolved', '==', false),
|
||||||
orderBy('popularityScore', 'desc'),
|
orderBy('popularityScore', 'desc'),
|
||||||
limit(count * 2)
|
limit(count)
|
||||||
)
|
)
|
||||||
const data = await getValues<Contract>(creatorContractsQuery)
|
return await getValues<Contract>(creatorContractsQuery)
|
||||||
const open = data
|
|
||||||
.filter((c) => c.closeTime && c.closeTime > Date.now())
|
|
||||||
.filter((c) => !excluding.includes(c.id))
|
|
||||||
|
|
||||||
return chooseRandomSubset(open, count)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getRecommendedContracts = async (
|
export const getRecommendedContracts = async (
|
||||||
contract: Contract,
|
contract: Contract,
|
||||||
|
excludeBettorId: string,
|
||||||
count: number
|
count: number
|
||||||
) => {
|
) => {
|
||||||
const { creatorId, groupSlugs, id } = contract
|
const { creatorId, groupSlugs, id } = contract
|
||||||
|
|
||||||
const [userContracts, groupContracts] = await Promise.all([
|
const [userContracts, groupContracts] = await Promise.all([
|
||||||
getRandTopCreatorContracts(creatorId, count, [id]),
|
getTopCreatorContracts(creatorId, count * 2),
|
||||||
groupSlugs && groupSlugs[0]
|
groupSlugs && groupSlugs[0]
|
||||||
? getRandTopGroupContracts(groupSlugs[0], count, [id])
|
? getTopGroupContracts(groupSlugs[0], count * 2)
|
||||||
: [],
|
: [],
|
||||||
])
|
])
|
||||||
|
|
||||||
const combined = uniqBy([...userContracts, ...groupContracts], (c) => c.id)
|
const combined = uniqBy([...userContracts, ...groupContracts], (c) => c.id)
|
||||||
|
|
||||||
return chooseRandomSubset(combined, count)
|
const open = combined
|
||||||
|
.filter((c) => c.closeTime && c.closeTime > Date.now())
|
||||||
|
.filter((c) => c.id !== id)
|
||||||
|
|
||||||
|
const [betOnContracts, nonBetOnContracts] = partition(
|
||||||
|
open,
|
||||||
|
(c) => c.uniqueBettorIds && c.uniqueBettorIds.includes(excludeBettorId)
|
||||||
|
)
|
||||||
|
const chosen = chooseRandomSubset(nonBetOnContracts, count)
|
||||||
|
if (chosen.length < count)
|
||||||
|
chosen.push(...chooseRandomSubset(betOnContracts, count - chosen.length))
|
||||||
|
|
||||||
|
return chosen
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRecentBetsAndComments(contract: Contract) {
|
export async function getRecentBetsAndComments(contract: Contract) {
|
||||||
|
|
|
@ -52,10 +52,9 @@ export async function getStaticPropz(props: {
|
||||||
const contract = (await getContractFromSlug(contractSlug)) || null
|
const contract = (await getContractFromSlug(contractSlug)) || null
|
||||||
const contractId = contract?.id
|
const contractId = contract?.id
|
||||||
|
|
||||||
const [bets, comments, recommendedContracts] = await Promise.all([
|
const [bets, comments] = await Promise.all([
|
||||||
contractId ? listAllBets(contractId) : [],
|
contractId ? listAllBets(contractId) : [],
|
||||||
contractId ? listAllComments(contractId) : [],
|
contractId ? listAllComments(contractId) : [],
|
||||||
contract ? getRecommendedContracts(contract, 6) : [],
|
|
||||||
])
|
])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -66,7 +65,6 @@ export async function getStaticPropz(props: {
|
||||||
// Limit the data sent to the client. Client will still load all bets and comments directly.
|
// Limit the data sent to the client. Client will still load all bets and comments directly.
|
||||||
bets: bets.slice(0, 5000),
|
bets: bets.slice(0, 5000),
|
||||||
comments: comments.slice(0, 1000),
|
comments: comments.slice(0, 1000),
|
||||||
recommendedContracts,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
revalidate: 60, // regenerate after a minute
|
revalidate: 60, // regenerate after a minute
|
||||||
|
@ -83,7 +81,6 @@ export default function ContractPage(props: {
|
||||||
bets: Bet[]
|
bets: Bet[]
|
||||||
comments: ContractComment[]
|
comments: ContractComment[]
|
||||||
slug: string
|
slug: string
|
||||||
recommendedContracts: Contract[]
|
|
||||||
backToHome?: () => void
|
backToHome?: () => void
|
||||||
}) {
|
}) {
|
||||||
props = usePropz(props, getStaticPropz) ?? {
|
props = usePropz(props, getStaticPropz) ?? {
|
||||||
|
@ -91,7 +88,6 @@ export default function ContractPage(props: {
|
||||||
username: '',
|
username: '',
|
||||||
comments: [],
|
comments: [],
|
||||||
bets: [],
|
bets: [],
|
||||||
recommendedContracts: [],
|
|
||||||
slug: '',
|
slug: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,15 +184,17 @@ export function ContractPageContent(
|
||||||
setShowConfetti(shouldSeeConfetti)
|
setShowConfetti(shouldSeeConfetti)
|
||||||
}, [contract, user])
|
}, [contract, user])
|
||||||
|
|
||||||
const [recommendedContracts, setRecommendedMarkets] = useState(
|
const [recommendedContracts, setRecommendedContracts] = useState<Contract[]>(
|
||||||
props.recommendedContracts
|
[]
|
||||||
)
|
)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (contract && recommendedContracts.length === 0) {
|
if (contract && user) {
|
||||||
getRecommendedContracts(contract, 6).then(setRecommendedMarkets)
|
getRecommendedContracts(contract, user.id, 6).then(
|
||||||
|
setRecommendedContracts
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [contract.id, recommendedContracts])
|
}, [contract.id, user?.id])
|
||||||
|
|
||||||
const { isResolved, question, outcomeType } = contract
|
const { isResolved, question, outcomeType } = contract
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user