Prettier everything

(Hopefully for the last time)
This commit is contained in:
Austin Chen 2021-12-13 23:30:09 -08:00
parent 6995802272
commit d4bb419478
11 changed files with 100 additions and 70 deletions

View File

@ -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>
) )
} }

View File

@ -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>

View File

@ -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(

View File

@ -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 />

View File

@ -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

View File

@ -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 }
} }

View File

@ -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,

View File

@ -1,2 +1 @@
export const randomString = () => Math.random().toString(16).substr(2, 14)
export const randomString = () => Math.random().toString(16).substr(2, 14)

View File

@ -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)
} }

View File

@ -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">

View File

@ -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>