Change outcomeType to include 'MULTI' and 'FREE_RESPONSE'

This commit is contained in:
James Grugett 2022-02-17 12:12:34 -06:00
parent 445176fad2
commit 58cec94b72
9 changed files with 27 additions and 37 deletions

View File

@ -80,7 +80,7 @@ export function getFreeAnswerAnte(
amount,
shares,
outcome: '0',
probBefore: 1,
probBefore: 0,
probAfter: 1,
createdTime,
isAnte: true,

View File

@ -13,8 +13,8 @@ export type Contract = {
lowercaseTags: string[]
visibility: 'public' | 'unlisted'
outcomeType: 'BINARY' | 'MULTI'
outcomes?: 'FREE_ANSWER' | string[]
outcomeType: 'BINARY' | 'MULTI' | 'FREE_RESPONSE'
multiOutcomes?: string[] // Used for outcomeType 'MULTI'.
mechanism: 'dpm-2'
phantomShares?: { [outcome: string]: number }
@ -34,3 +34,5 @@ export type Contract = {
volume24Hours: number
volume7Days: number
}
export type outcomeType = 'BINARY' | 'MULTI' | 'FREE_RESPONSE'

View File

@ -1,5 +1,5 @@
import { calcStartPool } from './antes'
import { Contract } from './contract'
import { Contract, outcomeType } from './contract'
import { User } from './user'
import { parseTags } from './util/parse'
import { removeUndefinedProps } from './util/object'
@ -9,7 +9,7 @@ export function getNewContract(
slug: string,
creator: User,
question: string,
outcomeType: 'BINARY' | 'MULTI',
outcomeType: outcomeType,
description: string,
initialProb: number,
ante: number,
@ -64,7 +64,6 @@ const getBinaryProps = (initialProb: number, ante: number) => {
pool: { YES: poolYes, NO: poolNo },
totalShares: { YES: sharesYes, NO: sharesNo },
totalBets: { YES: poolYes, NO: poolNo },
outcomes: undefined,
}
}
@ -73,8 +72,6 @@ const getFreeAnswerProps = (ante: number) => {
pool: { '0': ante },
totalShares: { '0': ante },
totalBets: { '0': ante },
phantomShares: undefined,
outcomes: 'FREE_ANSWER' as const,
}
}

View File

@ -44,13 +44,10 @@ export const createAnswer = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
if (
contract.outcomeType !== 'MULTI' ||
contract.outcomes !== 'FREE_ANSWER'
)
if (contract.outcomeType !== 'FREE_RESPONSE')
return {
status: 'error',
message: 'Requires a multi, free answer contract',
message: 'Requires a free response contract',
}
const { closeTime } = contract

View File

@ -2,7 +2,7 @@ import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { chargeUser, getUser } from './utils'
import { Contract } from '../../common/contract'
import { Contract, outcomeType } from '../../common/contract'
import { slugify } from '../../common/util/slugify'
import { randomString } from '../../common/util/random'
import { getNewContract } from '../../common/new-contract'
@ -19,7 +19,7 @@ export const createContract = functions
async (
data: {
question: string
outcomeType: 'BINARY' | 'MULTI'
outcomeType: outcomeType
description: string
initialProb: number
ante: number
@ -40,7 +40,7 @@ export const createContract = functions
return { status: 'error', message: 'Missing question field' }
let outcomeType = data.outcomeType ?? 'BINARY'
if (outcomeType !== 'BINARY' && outcomeType !== 'MULTI')
if (!['BINARY', 'MULTI', 'FREE_RESPONSE'].includes(outcomeType))
return { status: 'error', message: 'Invalid outcomeType' }
if (
@ -106,7 +106,7 @@ export const createContract = functions
)
await yesBetDoc.set(yesBet)
await noBetDoc.set(noBet)
} else if (outcomeType === 'MULTI') {
} else if (outcomeType === 'FREE_RESPONSE') {
const noneAnswerDoc = firestore
.collection(`contracts/${contract.id}/answers`)
.doc('0')

View File

@ -42,12 +42,11 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
const { closeTime, outcomes } = contract
const { closeTime, outcomeType } = contract
if (closeTime && Date.now() > closeTime)
return { status: 'error', message: 'Trading is closed' }
const isFreeAnswer = outcomes === 'FREE_ANSWER'
if (isFreeAnswer) {
if (outcomeType === 'FREE_RESPONSE') {
const answerSnap = await transaction.get(
contractDoc.collection('answers').doc(outcome)
)
@ -60,21 +59,15 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
.doc()
const { newBet, newPool, newTotalShares, newTotalBets, newBalance } =
isFreeAnswer
? getNewMultiBetInfo(
user,
outcome,
amount,
contract as any,
newBetDoc.id
)
: getNewBinaryBetInfo(
outcomeType === 'BINARY'
? getNewBinaryBetInfo(
user,
outcome as 'YES' | 'NO',
amount,
contract,
newBetDoc.id
)
: getNewMultiBetInfo(user, outcome, amount, contract, newBetDoc.id)
transaction.create(newBetDoc, newBet)
transaction.update(contractDoc, {

View File

@ -35,7 +35,7 @@ export const resolveMarket = functions
if (outcomeType === 'BINARY') {
if (!['YES', 'NO', 'MKT', 'CANCEL'].includes(outcome))
return { status: 'error', message: 'Invalid outcome' }
} else if (outcomeType === 'MULTI') {
} else if (outcomeType === 'FREE_RESPONSE') {
if (outcome !== 'CANCEL' && isNaN(+outcome))
return { status: 'error', message: 'Invalid outcome' }
} else {

View File

@ -42,7 +42,7 @@ export async function getStaticProps(props: {
const [bets, comments, answers] = await Promise.all([
contractId ? listAllBets(contractId) : [],
contractId ? listAllComments(contractId) : [],
contractId && contract.outcomes === 'FREE_ANSWER'
contractId && contract.outcomeType === 'FREE_RESPONSE'
? listAllAnswers(contractId)
: [],
])
@ -120,7 +120,7 @@ export default function ContractPage(props: {
comments={comments ?? []}
folds={folds}
>
{contract.outcomes === 'FREE_ANSWER' && (
{contract.outcomeType === 'FREE_RESPONSE' && (
<>
<Spacer h={4} />
<AnswersPanel

View File

@ -18,6 +18,7 @@ import { ProbabilitySelector } from '../components/probability-selector'
import { parseWordsAsTags } from '../../common/util/parse'
import { TagsList } from '../components/tags-list'
import { Row } from '../components/layout/row'
import { outcomeType } from '../../common/contract'
export default function Create() {
const [question, setQuestion] = useState('')
@ -62,7 +63,7 @@ export function NewContract(props: { question: string; tag?: string }) {
createContract({}).catch() // warm up function
}, [])
const [outcomeType, setOutcomeType] = useState<'BINARY' | 'MULTI'>('BINARY')
const [outcomeType, setOutcomeType] = useState<outcomeType>('BINARY')
const [initialProb, setInitialProb] = useState(50)
const [description, setDescription] = useState('')
const [tagText, setTagText] = useState<string>(tag ?? '')
@ -143,7 +144,7 @@ export function NewContract(props: { question: string; tag?: string }) {
name="opt"
checked={outcomeType === 'BINARY'}
value="BINARY"
onChange={(e) => setOutcomeType(e.target.value as 'BINARY')}
onChange={() => setOutcomeType('BINARY')}
/>
<span className="label-text">Yes / No</span>
</label>
@ -153,9 +154,9 @@ export function NewContract(props: { question: string; tag?: string }) {
className="radio"
type="radio"
name="opt"
checked={outcomeType === 'MULTI'}
value="MULTI"
onChange={(e) => setOutcomeType(e.target.value as 'MULTI')}
checked={outcomeType === 'FREE_RESPONSE'}
value="FREE_RESPONSE"
onChange={() => setOutcomeType('FREE_RESPONSE')}
/>
<span className="label-text">Free response</span>
</label>