From 4d9e2df51fcda0cd8d269273e64075155444d349 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Mon, 2 May 2022 11:56:45 -0400 Subject: [PATCH] basic market categories --- common/categories.ts | 43 +++++++++++++++++++ common/contract.ts | 2 + common/new-contract.ts | 3 ++ functions/src/create-contract.ts | 10 ++++- .../contract/contract-info-dialog.tsx | 10 ++++- web/pages/create.tsx | 36 ++++++++++------ 6 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 common/categories.ts diff --git a/common/categories.ts b/common/categories.ts new file mode 100644 index 00000000..2991135c --- /dev/null +++ b/common/categories.ts @@ -0,0 +1,43 @@ +export type category = + | 'sports' + | 'politics' + | 'technology' + | 'science' + | 'manifold' + | 'geopolitics' + | 'personal' + | 'fun' + | 'business' + | 'finance' + | 'society' + | 'entertainment' + | 'gaming' + | 'crypto' + | 'health' + | 'other' + +export const CATEGORIES = { + politics: 'Politics', + personal: 'Personal', + friends: 'Friends / Community', + technology: 'Technology', + gaming: 'Gaming / Esports', + science: 'Science', + manifold: 'Manifold Markets', + society: 'Society', + sports: 'Sports', + geopolitics: 'Geopolitics', + fun: 'Goofing around', + business: 'Business', + finance: 'Finance', + crypto: 'Crypto', + health: 'Health', + entertainment: 'Entertainment', + other: 'Other', +} + +export const TO_CATEGORY = Object.fromEntries( + Object.entries(CATEGORIES).map(([k, v]) => [v, k]) +) + +export const CATEGORY_LIST = Object.keys(CATEGORIES) as category[] diff --git a/common/contract.ts b/common/contract.ts index 82a330b5..5d2736e6 100644 --- a/common/contract.ts +++ b/common/contract.ts @@ -1,4 +1,5 @@ import { Answer } from './answer' +import { category } from './categories' import { Fees } from './fees' export type FullContract< @@ -15,6 +16,7 @@ export type FullContract< question: string description: string // More info about what the contract is about + category: category tags: string[] lowercaseTags: string[] visibility: 'public' | 'unlisted' diff --git a/common/new-contract.ts b/common/new-contract.ts index b86ebb71..9058d019 100644 --- a/common/new-contract.ts +++ b/common/new-contract.ts @@ -11,6 +11,7 @@ import { User } from './user' import { parseTags } from './util/parse' import { removeUndefinedProps } from './util/object' import { calcDpmInitialPool } from './calculate-dpm' +import { category } from './categories' export function getNewContract( id: string, @@ -22,6 +23,7 @@ export function getNewContract( initialProb: number, ante: number, closeTime: number, + category: category, extraTags: string[] ) { const tags = parseTags( @@ -48,6 +50,7 @@ export function getNewContract( question: question.trim(), description: description.trim(), + category, tags, lowercaseTags, visibility: 'public', diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index ae7b0ad8..931a5460 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -26,6 +26,7 @@ import { MINIMUM_ANTE, } from '../../common/antes' import { getNoneAnswer } from '../../common/answer' +import { category, CATEGORY_LIST } from '../../common/categories' export const createContract = functions .runWith({ minInstances: 1 }) @@ -35,6 +36,7 @@ export const createContract = functions question: string outcomeType: outcomeType description: string + category: category initialProb: number ante: number closeTime: number @@ -48,7 +50,8 @@ export const createContract = functions const creator = await getUser(userId) if (!creator) return { status: 'error', message: 'User not found' } - let { question, description, initialProb, closeTime, tags } = data + let { question, description, initialProb, closeTime, tags, category } = + data if (!question || typeof question != 'string') return { status: 'error', message: 'Missing or invalid question field' } @@ -58,6 +61,10 @@ export const createContract = functions return { status: 'error', message: 'Invalid description field' } description = description.slice(0, MAX_DESCRIPTION_LENGTH) + if (category !== undefined && !CATEGORY_LIST.includes(category)) + return { status: 'error', message: 'Invalid category' } + + // deprecated: if (tags !== undefined && !_.isArray(tags)) return { status: 'error', message: 'Invalid tags field' } tags = tags?.map((tag) => tag.toString().slice(0, MAX_TAG_LENGTH)) @@ -114,6 +121,7 @@ export const createContract = functions initialProb, ante, closeTime, + category, tags ?? [] ) diff --git a/web/components/contract/contract-info-dialog.tsx b/web/components/contract/contract-info-dialog.tsx index 79ec45ed..9479bd24 100644 --- a/web/components/contract/contract-info-dialog.tsx +++ b/web/components/contract/contract-info-dialog.tsx @@ -4,6 +4,7 @@ import dayjs from 'dayjs' import _ from 'lodash' import { useState } from 'react' import { Bet } from '../../../common/bet' +import { CATEGORIES } from '../../../common/categories' import { Contract } from '../../../common/contract' import { formatMoney } from '../../../common/util/format' @@ -28,7 +29,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) { const formatTime = (dt: number) => dayjs(dt).format('MMM DD, YYYY hh:mm a z') - const { createdTime, closeTime, resolutionTime } = contract + const { createdTime, closeTime, resolutionTime, category } = contract const tradersCount = _.uniqBy(bets, 'userId').length return ( @@ -52,6 +53,13 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
Stats
+ {category && ( + + + + + )} + diff --git a/web/pages/create.tsx b/web/pages/create.tsx index 9f4dae84..941fc0ee 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -19,6 +19,12 @@ import { Row } from '../components/layout/row' import { MAX_DESCRIPTION_LENGTH, outcomeType } from '../../common/contract' import { formatMoney } from '../../common/util/format' import { useHasCreatedContractToday } from '../hooks/use-has-created-contract-today' +import { + CATEGORIES, + category, + CATEGORY_LIST, + TO_CATEGORY, +} from '../../common/categories' export default function Create() { const [question, setQuestion] = useState('') @@ -67,6 +73,7 @@ export function NewContract(props: { question: string; tag?: string }) { const [outcomeType, setOutcomeType] = useState('BINARY') const [initialProb, setInitialProb] = useState(50) const [description, setDescription] = useState('') + const [category, setCategory] = useState(CATEGORY_LIST[0]) const [tagText, setTagText] = useState(tag ?? '') const tags = parseWordsAsTags(tagText) @@ -117,6 +124,7 @@ export function NewContract(props: { question: string; tag?: string }) { initialProb, ante, closeTime, + category, tags, }).then((r) => r.data || {}) @@ -199,25 +207,27 @@ export function NewContract(props: { question: string; tag?: string }) { /> - {/* +
- setTagText(e.target.value || '')} - /> -
*/} + + - -
Category{CATEGORIES[category]}
Market created {formatTime(createdTime)}