Prettier everything
(Hopefully for the last time)
This commit is contained in:
parent
6995802272
commit
d4bb419478
|
@ -51,7 +51,9 @@ export const ContractOverview = (props: {
|
||||||
|
|
||||||
<Spacer h={12} />
|
<Spacer h={12} />
|
||||||
|
|
||||||
<div className="text-gray-600 whitespace-pre-line">{contract.description}</div>
|
<div className="text-gray-600 whitespace-pre-line">
|
||||||
|
{contract.description}
|
||||||
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,23 @@ import dayjs from 'dayjs'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useUser } from '../hooks/use-user'
|
import { useUser } from '../hooks/use-user'
|
||||||
import { Contract, deleteContract, listContracts } from '../lib/firebase/contracts'
|
import {
|
||||||
|
Contract,
|
||||||
|
deleteContract,
|
||||||
|
listContracts,
|
||||||
|
} from '../lib/firebase/contracts'
|
||||||
|
|
||||||
function ContractCard(props: { contract: Contract }) {
|
function ContractCard(props: { contract: Contract }) {
|
||||||
const { contract } = props
|
const { contract } = props
|
||||||
|
|
||||||
// only show delete button if there's not bets
|
// only show delete button if there's not bets
|
||||||
const showDelete = contract.pot.YES === contract.seedAmounts.YES
|
const showDelete =
|
||||||
&& contract.pot.NO === contract.seedAmounts.NO
|
contract.pot.YES === contract.seedAmounts.YES &&
|
||||||
|
contract.pot.NO === contract.seedAmounts.NO
|
||||||
|
|
||||||
const [isDeleted, setIsDeleted] = useState(false) // temporary fix until we stream changes
|
const [isDeleted, setIsDeleted] = useState(false) // temporary fix until we stream changes
|
||||||
|
|
||||||
if (isDeleted)
|
if (isDeleted) return <></>
|
||||||
return <></>
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li>
|
<li>
|
||||||
|
@ -40,10 +44,10 @@ function ContractCard(props: { contract: Contract }) {
|
||||||
</time>
|
</time>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{showDelete &&
|
{showDelete && (
|
||||||
<button
|
<button
|
||||||
className="btn btn-xs btn-error btn-outline ml-2"
|
className="btn btn-xs btn-error btn-outline ml-2"
|
||||||
onClick={async e => {
|
onClick={async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
await deleteContract(contract.id)
|
await deleteContract(contract.id)
|
||||||
setIsDeleted(true)
|
setIsDeleted(true)
|
||||||
|
@ -51,7 +55,7 @@ function ContractCard(props: { contract: Contract }) {
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,11 +34,15 @@ function SignInLink(props: { darkBackground?: boolean }) {
|
||||||
{user ? (
|
{user ? (
|
||||||
<>
|
<>
|
||||||
<Link href="/contract">
|
<Link href="/contract">
|
||||||
<a className={clsx('text-base font-medium', themeClasses)}>Create a market</a>
|
<a className={clsx('text-base font-medium', themeClasses)}>
|
||||||
|
Create a market
|
||||||
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link href="/account">
|
<Link href="/account">
|
||||||
<a className={clsx('text-base font-medium', themeClasses)}>{user.name}</a>
|
<a className={clsx('text-base font-medium', themeClasses)}>
|
||||||
|
{user.name}
|
||||||
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
) : showLogin ? (
|
) : showLogin ? (
|
||||||
|
@ -70,7 +74,10 @@ export function Header(props: { darkBackground?: boolean }) {
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
<a className="flex flex-row items-center align-items-center h-6 sm:h-10">
|
<a className="flex flex-row items-center align-items-center h-6 sm:h-10">
|
||||||
<div className="inline-block mr-3">
|
<div className="inline-block mr-3">
|
||||||
<img className="h-6 sm:h-10 w-6 sm:w-10" src="/logo-icon.svg" />
|
<img
|
||||||
|
className="h-6 sm:h-10 w-6 sm:w-10"
|
||||||
|
src="/logo-icon.svg"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|
|
@ -18,8 +18,8 @@ export const Hero = () => {
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="mt-3 text-base text-gray-300 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
|
<p className="mt-3 text-base text-gray-300 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
|
||||||
Better forecasting through play-money prediction
|
Better forecasting through play-money prediction markets for
|
||||||
markets for you and your community
|
you and your community
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-10 sm:mt-12">
|
<div className="mt-10 sm:mt-12">
|
||||||
<ConvertKitEmailForm />
|
<ConvertKitEmailForm />
|
||||||
|
|
|
@ -31,10 +31,10 @@ export function ResolutionPanel(props: {
|
||||||
outcome === 'YES'
|
outcome === 'YES'
|
||||||
? 'btn-primary'
|
? 'btn-primary'
|
||||||
: outcome === 'NO'
|
: outcome === 'NO'
|
||||||
? 'bg-red-400 hover:bg-red-500'
|
? 'bg-red-400 hover:bg-red-500'
|
||||||
: outcome === 'CANCEL'
|
: outcome === 'CANCEL'
|
||||||
? 'bg-yellow-400 hover:bg-yellow-500'
|
? 'bg-yellow-400 hover:bg-yellow-500'
|
||||||
: 'btn-disabled'
|
: 'btn-disabled'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
|
|
|
@ -4,49 +4,53 @@ import { randomString } from '../util/random-string'
|
||||||
import { slugify } from '../util/slugify'
|
import { slugify } from '../util/slugify'
|
||||||
|
|
||||||
// consider moving to cloud function for security
|
// consider moving to cloud function for security
|
||||||
export async function createContract(question: string, description: string, initialProb: number, creator: User) {
|
export async function createContract(
|
||||||
const slug = slugify(question).substr(0, 35)
|
question: string,
|
||||||
|
description: string,
|
||||||
|
initialProb: number,
|
||||||
|
creator: User
|
||||||
|
) {
|
||||||
|
const slug = slugify(question).substr(0, 35)
|
||||||
|
|
||||||
const preexistingContract = await getContract(slug)
|
const preexistingContract = await getContract(slug)
|
||||||
|
|
||||||
const contractId = preexistingContract
|
const contractId = preexistingContract ? slug + '-' + randomString() : slug
|
||||||
? slug + '-' + randomString()
|
|
||||||
: slug
|
|
||||||
|
|
||||||
const { seedYes, seedNo } = calcSeedBets(initialProb)
|
const { seedYes, seedNo } = calcSeedBets(initialProb)
|
||||||
|
|
||||||
const contract: Contract = {
|
const contract: Contract = {
|
||||||
id: contractId,
|
id: contractId,
|
||||||
outcomeType: 'BINARY',
|
outcomeType: 'BINARY',
|
||||||
|
|
||||||
creatorId: creator.id,
|
creatorId: creator.id,
|
||||||
creatorName: creator.name,
|
creatorName: creator.name,
|
||||||
|
|
||||||
question: question.trim(),
|
question: question.trim(),
|
||||||
description: description.trim(),
|
description: description.trim(),
|
||||||
|
|
||||||
seedAmounts: { YES: seedYes, NO: seedNo },
|
seedAmounts: { YES: seedYes, NO: seedNo },
|
||||||
pot: { YES: seedYes, NO: seedNo },
|
pot: { YES: seedYes, NO: seedNo },
|
||||||
isResolved: false,
|
isResolved: false,
|
||||||
|
|
||||||
// TODO: Set create time to Firestore timestamp
|
// TODO: Set create time to Firestore timestamp
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
lastUpdatedTime: Date.now(),
|
lastUpdatedTime: Date.now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
await setContract(contract)
|
await setContract(contract)
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calcSeedBets(initialProb: number, initialCapital = 1000) {
|
export function calcSeedBets(initialProb: number, initialCapital = 1000) {
|
||||||
const p = initialProb / 100.0
|
const p = initialProb / 100.0
|
||||||
|
|
||||||
const seedYes = p === 0.5
|
const seedYes =
|
||||||
? p * initialCapital
|
p === 0.5
|
||||||
: -(initialCapital * (-p + Math.sqrt((-1 + p) * -p))) / (-1 + 2 * p)
|
? p * initialCapital
|
||||||
|
: -(initialCapital * (-p + Math.sqrt((-1 + p) * -p))) / (-1 + 2 * p)
|
||||||
|
|
||||||
const seedNo = initialCapital - seedYes
|
const seedNo = initialCapital - seedYes
|
||||||
|
|
||||||
return { seedYes, seedNo }
|
return { seedYes, seedNo }
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,17 @@ function makeWeights(bids: Bid[]) {
|
||||||
|
|
||||||
// First pass: calculate all the weights
|
// First pass: calculate all the weights
|
||||||
for (const { yesBid, noBid } of bids) {
|
for (const { yesBid, noBid } of bids) {
|
||||||
const yesWeight = yesBid * Math.pow(noPot, 2) / (Math.pow(yesPot, 2) + yesBid * yesPot) || 0
|
const yesWeight =
|
||||||
const noWeight = noBid * Math.pow(yesPot, 2) / (Math.pow(noPot, 2) + noBid * noPot) || 0
|
(yesBid * Math.pow(noPot, 2)) / (Math.pow(yesPot, 2) + yesBid * yesPot) ||
|
||||||
|
0
|
||||||
|
const noWeight =
|
||||||
|
(noBid * Math.pow(yesPot, 2)) / (Math.pow(noPot, 2) + noBid * noPot) || 0
|
||||||
|
|
||||||
// Note: Need to calculate weights BEFORE updating pot
|
// Note: Need to calculate weights BEFORE updating pot
|
||||||
yesPot += yesBid
|
yesPot += yesBid
|
||||||
noPot += noBid
|
noPot += noBid
|
||||||
const prob = Math.pow(yesPot, 2) / (Math.pow(yesPot, 2) + Math.pow(noPot, 2))
|
const prob =
|
||||||
|
Math.pow(yesPot, 2) / (Math.pow(yesPot, 2) + Math.pow(noPot, 2))
|
||||||
|
|
||||||
weights.push({
|
weights.push({
|
||||||
yesBid,
|
yesBid,
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
|
export const randomString = () => Math.random().toString(16).substr(2, 14)
|
||||||
export const randomString = () => Math.random().toString(16).substr(2, 14)
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
export const slugify = (text: any, separator = '-'): string => {
|
export const slugify = (text: any, separator = '-'): string => {
|
||||||
return text
|
return text
|
||||||
.toString()
|
.toString()
|
||||||
.normalize('NFD') // split an accented letter in the base letter and the acent
|
.normalize('NFD') // split an accented letter in the base letter and the acent
|
||||||
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
|
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
|
.replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
|
||||||
.replace(/\s+/g, separator)
|
.replace(/\s+/g, separator)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,12 @@ function UserCard(props: { user: User }) {
|
||||||
<Row className="card glass lg:card-side shadow-xl hover:shadow-xl text-neutral-content bg-green-600 hover:bg-green-600 transition-all max-w-sm mx-auto my-12">
|
<Row className="card glass lg:card-side shadow-xl hover:shadow-xl text-neutral-content bg-green-600 hover:bg-green-600 transition-all max-w-sm mx-auto my-12">
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
{user?.avatarUrl && (
|
{user?.avatarUrl && (
|
||||||
<img src={user.avatarUrl} className="rounded-lg shadow-lg" width={96} height={96} />
|
<img
|
||||||
|
src={user.avatarUrl}
|
||||||
|
className="rounded-lg shadow-lg"
|
||||||
|
width={96}
|
||||||
|
height={96}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="max-w-md card-body">
|
<div className="max-w-md card-body">
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { Title } from '../../components/title'
|
||||||
import { useUser } from '../../hooks/use-user'
|
import { useUser } from '../../hooks/use-user'
|
||||||
import { createContract } from '../../lib/service/create-contract'
|
import { createContract } from '../../lib/service/create-contract'
|
||||||
|
|
||||||
|
|
||||||
// Allow user to create a new contract
|
// Allow user to create a new contract
|
||||||
export default function NewContract() {
|
export default function NewContract() {
|
||||||
const creator = useUser()
|
const creator = useUser()
|
||||||
|
@ -24,7 +23,12 @@ export default function NewContract() {
|
||||||
|
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
|
|
||||||
const contract = await createContract(question, description, initialProb, creator)
|
const contract = await createContract(
|
||||||
|
question,
|
||||||
|
description,
|
||||||
|
initialProb,
|
||||||
|
creator
|
||||||
|
)
|
||||||
await router.push(`contract/${contract.id}`)
|
await router.push(`contract/${contract.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +55,7 @@ export default function NewContract() {
|
||||||
placeholder="e.g. Will the FDA approve Paxlovid before Jun 2nd, 2022?"
|
placeholder="e.g. Will the FDA approve Paxlovid before Jun 2nd, 2022?"
|
||||||
className="input"
|
className="input"
|
||||||
value={question}
|
value={question}
|
||||||
onChange={e => setQuestion(e.target.value || '')}
|
onChange={(e) => setQuestion(e.target.value || '')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -66,7 +70,7 @@ export default function NewContract() {
|
||||||
className="textarea h-24 textarea-bordered"
|
className="textarea h-24 textarea-bordered"
|
||||||
placeholder={descriptionPlaceholder}
|
placeholder={descriptionPlaceholder}
|
||||||
value={description}
|
value={description}
|
||||||
onChange={e => setDescription(e.target.value || '')}
|
onChange={(e) => setDescription(e.target.value || '')}
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -74,7 +78,9 @@ export default function NewContract() {
|
||||||
|
|
||||||
<div className="form-control">
|
<div className="form-control">
|
||||||
<label className="label">
|
<label className="label">
|
||||||
<span className="label-text">Initial probability: {initialProb}%</span>
|
<span className="label-text">
|
||||||
|
Initial probability: {initialProb}%
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
@ -82,7 +88,7 @@ export default function NewContract() {
|
||||||
min="1"
|
min="1"
|
||||||
max={99}
|
max={99}
|
||||||
value={initialProb}
|
value={initialProb}
|
||||||
onChange={e => setInitialProb(parseInt(e.target.value))}
|
onChange={(e) => setInitialProb(parseInt(e.target.value))}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user