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} />
|
||||
|
||||
<div className="text-gray-600 whitespace-pre-line">{contract.description}</div>
|
||||
<div className="text-gray-600 whitespace-pre-line">
|
||||
{contract.description}
|
||||
</div>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,19 +2,23 @@ import dayjs from 'dayjs'
|
|||
import Link from 'next/link'
|
||||
import { useEffect, useState } from 'react'
|
||||
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 }) {
|
||||
const { contract } = props
|
||||
|
||||
// only show delete button if there's not bets
|
||||
const showDelete = contract.pot.YES === contract.seedAmounts.YES
|
||||
&& contract.pot.NO === contract.seedAmounts.NO
|
||||
const showDelete =
|
||||
contract.pot.YES === contract.seedAmounts.YES &&
|
||||
contract.pot.NO === contract.seedAmounts.NO
|
||||
|
||||
const [isDeleted, setIsDeleted] = useState(false) // temporary fix until we stream changes
|
||||
|
||||
if (isDeleted)
|
||||
return <></>
|
||||
if (isDeleted) return <></>
|
||||
|
||||
return (
|
||||
<li>
|
||||
|
@ -40,10 +44,10 @@ function ContractCard(props: { contract: Contract }) {
|
|||
</time>
|
||||
</p>
|
||||
|
||||
{showDelete &&
|
||||
{showDelete && (
|
||||
<button
|
||||
className="btn btn-xs btn-error btn-outline ml-2"
|
||||
onClick={async e => {
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
await deleteContract(contract.id)
|
||||
setIsDeleted(true)
|
||||
|
@ -51,7 +55,7 @@ function ContractCard(props: { contract: Contract }) {
|
|||
>
|
||||
Delete
|
||||
</button>
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -34,11 +34,15 @@ function SignInLink(props: { darkBackground?: boolean }) {
|
|||
{user ? (
|
||||
<>
|
||||
<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 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>
|
||||
</>
|
||||
) : showLogin ? (
|
||||
|
@ -70,7 +74,10 @@ export function Header(props: { darkBackground?: boolean }) {
|
|||
<Link href="/">
|
||||
<a className="flex flex-row items-center align-items-center h-6 sm:h-10">
|
||||
<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>
|
||||
<span
|
||||
className={clsx(
|
||||
|
|
|
@ -18,8 +18,8 @@ export const Hero = () => {
|
|||
</div>
|
||||
</h1>
|
||||
<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
|
||||
markets for you and your community
|
||||
Better forecasting through play-money prediction markets for
|
||||
you and your community
|
||||
</p>
|
||||
<div className="mt-10 sm:mt-12">
|
||||
<ConvertKitEmailForm />
|
||||
|
|
|
@ -31,10 +31,10 @@ export function ResolutionPanel(props: {
|
|||
outcome === 'YES'
|
||||
? 'btn-primary'
|
||||
: outcome === 'NO'
|
||||
? 'bg-red-400 hover:bg-red-500'
|
||||
: outcome === 'CANCEL'
|
||||
? 'bg-yellow-400 hover:bg-yellow-500'
|
||||
: 'btn-disabled'
|
||||
? 'bg-red-400 hover:bg-red-500'
|
||||
: outcome === 'CANCEL'
|
||||
? 'bg-yellow-400 hover:bg-yellow-500'
|
||||
: 'btn-disabled'
|
||||
|
||||
return (
|
||||
<Col
|
||||
|
|
|
@ -4,49 +4,53 @@ import { randomString } from '../util/random-string'
|
|||
import { slugify } from '../util/slugify'
|
||||
|
||||
// consider moving to cloud function for security
|
||||
export async function createContract(question: string, description: string, initialProb: number, creator: User) {
|
||||
const slug = slugify(question).substr(0, 35)
|
||||
export async function createContract(
|
||||
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
|
||||
? slug + '-' + randomString()
|
||||
: slug
|
||||
const contractId = preexistingContract ? slug + '-' + randomString() : slug
|
||||
|
||||
const { seedYes, seedNo } = calcSeedBets(initialProb)
|
||||
const { seedYes, seedNo } = calcSeedBets(initialProb)
|
||||
|
||||
const contract: Contract = {
|
||||
id: contractId,
|
||||
outcomeType: 'BINARY',
|
||||
const contract: Contract = {
|
||||
id: contractId,
|
||||
outcomeType: 'BINARY',
|
||||
|
||||
creatorId: creator.id,
|
||||
creatorName: creator.name,
|
||||
creatorId: creator.id,
|
||||
creatorName: creator.name,
|
||||
|
||||
question: question.trim(),
|
||||
description: description.trim(),
|
||||
question: question.trim(),
|
||||
description: description.trim(),
|
||||
|
||||
seedAmounts: { YES: seedYes, NO: seedNo },
|
||||
pot: { YES: seedYes, NO: seedNo },
|
||||
isResolved: false,
|
||||
seedAmounts: { YES: seedYes, NO: seedNo },
|
||||
pot: { YES: seedYes, NO: seedNo },
|
||||
isResolved: false,
|
||||
|
||||
// TODO: Set create time to Firestore timestamp
|
||||
createdTime: Date.now(),
|
||||
lastUpdatedTime: Date.now(),
|
||||
}
|
||||
// TODO: Set create time to Firestore timestamp
|
||||
createdTime: Date.now(),
|
||||
lastUpdatedTime: Date.now(),
|
||||
}
|
||||
|
||||
await setContract(contract)
|
||||
await setContract(contract)
|
||||
|
||||
return contract
|
||||
return contract
|
||||
}
|
||||
|
||||
export function calcSeedBets(initialProb: number, initialCapital = 1000) {
|
||||
const p = initialProb / 100.0
|
||||
const p = initialProb / 100.0
|
||||
|
||||
const seedYes = p === 0.5
|
||||
? p * initialCapital
|
||||
: -(initialCapital * (-p + Math.sqrt((-1 + p) * -p))) / (-1 + 2 * p)
|
||||
const seedYes =
|
||||
p === 0.5
|
||||
? 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
|
||||
for (const { yesBid, noBid } of bids) {
|
||||
const yesWeight = 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
|
||||
const yesWeight =
|
||||
(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
|
||||
yesPot += yesBid
|
||||
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({
|
||||
yesBid,
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
|
||||
export const randomString = () => Math.random().toString(16).substr(2, 14)
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
export const slugify = (text: any, separator = '-'): string => {
|
||||
return text
|
||||
.toString()
|
||||
.normalize('NFD') // split an accented letter in the base letter and the acent
|
||||
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
|
||||
.replace(/\s+/g, separator)
|
||||
return text
|
||||
.toString()
|
||||
.normalize('NFD') // split an accented letter in the base letter and the acent
|
||||
.replace(/[\u0300-\u036f]/g, '') // remove all previously split accents
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9 ]/g, '') // remove all chars not letters, numbers and spaces (to be replaced)
|
||||
.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">
|
||||
<div className="p-4">
|
||||
{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 className="max-w-md card-body">
|
||||
|
|
|
@ -8,7 +8,6 @@ import { Title } from '../../components/title'
|
|||
import { useUser } from '../../hooks/use-user'
|
||||
import { createContract } from '../../lib/service/create-contract'
|
||||
|
||||
|
||||
// Allow user to create a new contract
|
||||
export default function NewContract() {
|
||||
const creator = useUser()
|
||||
|
@ -24,7 +23,12 @@ export default function NewContract() {
|
|||
|
||||
setIsSubmitting(true)
|
||||
|
||||
const contract = await createContract(question, description, initialProb, creator)
|
||||
const contract = await createContract(
|
||||
question,
|
||||
description,
|
||||
initialProb,
|
||||
creator
|
||||
)
|
||||
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?"
|
||||
className="input"
|
||||
value={question}
|
||||
onChange={e => setQuestion(e.target.value || '')}
|
||||
onChange={(e) => setQuestion(e.target.value || '')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -66,7 +70,7 @@ export default function NewContract() {
|
|||
className="textarea h-24 textarea-bordered"
|
||||
placeholder={descriptionPlaceholder}
|
||||
value={description}
|
||||
onChange={e => setDescription(e.target.value || '')}
|
||||
onChange={(e) => setDescription(e.target.value || '')}
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
|
@ -74,7 +78,9 @@ export default function NewContract() {
|
|||
|
||||
<div className="form-control">
|
||||
<label className="label">
|
||||
<span className="label-text">Initial probability: {initialProb}%</span>
|
||||
<span className="label-text">
|
||||
Initial probability: {initialProb}%
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
|
@ -82,7 +88,7 @@ export default function NewContract() {
|
|||
min="1"
|
||||
max={99}
|
||||
value={initialProb}
|
||||
onChange={e => setInitialProb(parseInt(e.target.value))}
|
||||
onChange={(e) => setInitialProb(parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user