diff --git a/web/lib/firebase/contracts.ts b/web/lib/firebase/contracts.ts
index 4942d721..652bec4b 100644
--- a/web/lib/firebase/contracts.ts
+++ b/web/lib/firebase/contracts.ts
@@ -51,11 +51,13 @@ export function compute(contract: Contract) {
const volume = pool.YES + pool.NO - startPool.YES - startPool.NO
const prob = pool.YES ** 2 / (pool.YES ** 2 + pool.NO ** 2)
const probPercent = Math.round(prob * 100) + '%'
+ const startProb =
+ startPool.YES ** 2 / (startPool.YES ** 2 + startPool.NO ** 2)
const createdDate = dayjs(createdTime).format('MMM D')
const resolvedDate = isResolved
? dayjs(resolutionTime).format('MMM D')
: undefined
- return { volume, probPercent, createdDate, resolvedDate }
+ return { volume, probPercent, startProb, createdDate, resolvedDate }
}
const db = getFirestore(app)
diff --git a/web/pages/make-predictions.tsx b/web/pages/make-predictions.tsx
new file mode 100644
index 00000000..7b8c8405
--- /dev/null
+++ b/web/pages/make-predictions.tsx
@@ -0,0 +1,223 @@
+import clsx from 'clsx'
+import Link from 'next/link'
+import { useState } from 'react'
+import { Col } from '../components/layout/col'
+import { Row } from '../components/layout/row'
+import { Spacer } from '../components/layout/spacer'
+import { Linkify } from '../components/linkify'
+import { Page } from '../components/page'
+import { Title } from '../components/title'
+import { useUser } from '../hooks/use-user'
+import { compute, Contract, path } from '../lib/firebase/contracts'
+import { createContract } from '../lib/service/create-contract'
+
+type Prediction = {
+ question: string
+ description: string
+ initialProb: number
+ createdUrl?: string
+}
+
+function toPrediction(contract: Contract): Prediction {
+ const { startProb } = compute(contract)
+ return {
+ question: contract.question,
+ description: contract.description,
+ initialProb: startProb * 100,
+ createdUrl: path(contract),
+ }
+}
+
+function PredictionRow(props: { prediction: Prediction }) {
+ const { prediction } = props
+ return (
+
+
+
+
+
+ {prediction.description}
+
+ {/* Initial probability */}
+
+
+
+ {prediction.initialProb.toFixed(0)}%
+
chance
+
+
+
+ {/* Current probability; hidden for now */}
+ {/*
+
+
+ {prediction.initialProb}%
chance
+
+
+
*/}
+
+ )
+}
+
+function PredictionList(props: { predictions: Prediction[] }) {
+ const { predictions } = props
+ return (
+
+ {predictions.map((prediction) =>
+ prediction.createdUrl ? (
+
+
+
+
+
+ ) : (
+
+ )
+ )}
+
+ )
+}
+
+const TEST_VALUE = `1. Biden approval rating (as per 538) is greater than 50%: 80%
+2. Court packing is clearly going to happen (new justices don't have to be appointed by end of year): 5%
+3. Yang is New York mayor: 80%
+4. Newsom recalled as CA governor: 5%
+5. At least $250 million in damage from BLM protests this year: 30%
+6. Significant capital gains tax hike (above 30% for highest bracket): 20%`
+
+export default function MakePredictions() {
+ const user = useUser()
+ const [predictionsString, setPredictionsString] = useState('')
+ const [description, setDescription] = useState('')
+ const [isSubmitting, setIsSubmitting] = useState(false)
+ const [createdContracts, setCreatedContracts] = useState([])
+
+ const bulkPlaceholder = `e.g.
+${TEST_VALUE}
+...
+`
+
+ const predictions: Prediction[] = []
+
+ // Parse bulkContracts, then run createContract for each
+ const lines = predictionsString ? predictionsString.split('\n') : []
+ for (const line of lines) {
+ // Parse line with regex
+ const matches = line.match(/^(.*):\s*(\d+)%\s*$/) || ['', '', '']
+ const [_, question, prob] = matches
+
+ if (!question || !prob) {
+ console.error('Invalid prediction: ', line)
+ continue
+ }
+
+ predictions.push({
+ question,
+ description,
+ initialProb: parseInt(prob),
+ })
+ }
+
+ async function createContracts() {
+ if (!user) {
+ // TODO: Convey error with snackbar/toast
+ console.error('You need to be signed in!')
+ return
+ }
+ setIsSubmitting(true)
+ for (const prediction of predictions) {
+ const contract = await createContract(
+ prediction.question,
+ prediction.description,
+ prediction.initialProb,
+ user
+ )
+ setCreatedContracts((prev) => [...prev, contract])
+ }
+ setPredictionsString('')
+ setIsSubmitting(false)
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ setDescription(e.target.value || '')}
+ />
+
+
+ {predictions.length > 0 && (
+
+ )}
+
+
+
+
+
+
+
+
+ {createdContracts.length > 0 && (
+ <>
+
+
+
+ >
+ )}
+
+ )
+}