Change lodash stuff so that it can be tree-shaken out of build (#233)
* Set common package.json sideEffects: false * Configure SWC to modularize lodash imports * Import specific lodash functions instead of _ * Add an eslint rule to avoid full lodash import
This commit is contained in:
parent
0803a15902
commit
47f10301c8
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
plugins: ['lodash'],
|
||||
extends: ['eslint:recommended'],
|
||||
env: {
|
||||
browser: true,
|
||||
|
@ -14,5 +15,6 @@ module.exports = {
|
|||
rules: {
|
||||
'no-unused-vars': 'off',
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'lodash/import-scope': [2, 'member'],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { range } from 'lodash'
|
||||
import { Bet, NumericBet } from './bet'
|
||||
import { getDpmProbability, getValueFromBucket } from './calculate-dpm'
|
||||
import {
|
||||
|
@ -11,7 +12,6 @@ import {
|
|||
import { User } from './user'
|
||||
import { LiquidityProvision } from './liquidity-provision'
|
||||
import { noFees } from './fees'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
export const FIXED_ANTE = 100
|
||||
|
||||
|
@ -127,11 +127,11 @@ export function getNumericAnte(
|
|||
const betShares = Math.sqrt(ante ** 2 / bucketCount)
|
||||
|
||||
const allOutcomeShares = Object.fromEntries(
|
||||
_.range(0, bucketCount).map((_, i) => [i, betShares])
|
||||
range(0, bucketCount).map((_, i) => [i, betShares])
|
||||
)
|
||||
|
||||
const allBetAmounts = Object.fromEntries(
|
||||
_.range(0, bucketCount).map((_, i) => [i, betAnte])
|
||||
range(0, bucketCount).map((_, i) => [i, betAnte])
|
||||
)
|
||||
|
||||
const anteBet: NumericBet = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { sum, groupBy, mapValues, sumBy } from 'lodash'
|
||||
|
||||
import { Binary, CPMM, FullContract } from './contract'
|
||||
import { CREATOR_FEE, Fees, LIQUIDITY_FEE, noFees, PLATFORM_FEE } from './fees'
|
||||
|
@ -278,16 +278,16 @@ export function getCpmmLiquidityPoolWeights(
|
|||
return liquidity
|
||||
})
|
||||
|
||||
const shareSum = _.sum(liquidityShares)
|
||||
const shareSum = sum(liquidityShares)
|
||||
|
||||
const weights = liquidityShares.map((s, i) => ({
|
||||
weight: s / shareSum,
|
||||
providerId: liquidities[i].userId,
|
||||
}))
|
||||
|
||||
const userWeights = _.groupBy(weights, (w) => w.providerId)
|
||||
const totalUserWeights = _.mapValues(userWeights, (userWeight) =>
|
||||
_.sumBy(userWeight, (w) => w.weight)
|
||||
const userWeights = groupBy(weights, (w) => w.providerId)
|
||||
const totalUserWeights = mapValues(userWeights, (userWeight) =>
|
||||
sumBy(userWeight, (w) => w.weight)
|
||||
)
|
||||
return totalUserWeights
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { cloneDeep, range, sum, sumBy, sortBy, mapValues } from 'lodash'
|
||||
import { Bet, NumericBet } from './bet'
|
||||
import {
|
||||
Binary,
|
||||
|
@ -24,7 +23,7 @@ export function getDpmOutcomeProbability(
|
|||
},
|
||||
outcome: string
|
||||
) {
|
||||
const squareSum = _.sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
const squareSum = sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
const shares = totalShares[outcome] ?? 0
|
||||
return shares ** 2 / squareSum
|
||||
}
|
||||
|
@ -32,8 +31,8 @@ export function getDpmOutcomeProbability(
|
|||
export function getDpmOutcomeProbabilities(totalShares: {
|
||||
[outcome: string]: number
|
||||
}) {
|
||||
const squareSum = _.sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
return _.mapValues(totalShares, (shares) => shares ** 2 / squareSum)
|
||||
const squareSum = sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
return mapValues(totalShares, (shares) => shares ** 2 / squareSum)
|
||||
}
|
||||
|
||||
export function getNumericBets(
|
||||
|
@ -44,20 +43,20 @@ export function getNumericBets(
|
|||
) {
|
||||
const { bucketCount } = contract
|
||||
const bucketNumber = parseInt(bucket)
|
||||
const buckets = _.range(0, bucketCount)
|
||||
const buckets = range(0, bucketCount)
|
||||
|
||||
const mean = bucketNumber / bucketCount
|
||||
|
||||
const allDensities = buckets.map((i) =>
|
||||
normpdf(i / bucketCount, mean, variance)
|
||||
)
|
||||
const densitySum = _.sum(allDensities)
|
||||
const densitySum = sum(allDensities)
|
||||
|
||||
const rawBetAmounts = allDensities
|
||||
.map((d) => (d / densitySum) * betAmount)
|
||||
.map((x) => (x >= 1 / bucketCount ? x : 0))
|
||||
|
||||
const rawSum = _.sum(rawBetAmounts)
|
||||
const rawSum = sum(rawBetAmounts)
|
||||
const scaledBetAmounts = rawBetAmounts.map((x) => (x / rawSum) * betAmount)
|
||||
|
||||
const bets = scaledBetAmounts
|
||||
|
@ -90,26 +89,24 @@ export const getValueFromBucket = (
|
|||
export const getExpectedValue = (contract: NumericContract) => {
|
||||
const { bucketCount, min, max, totalShares } = contract
|
||||
|
||||
const totalShareSum = _.sumBy(
|
||||
const totalShareSum = sumBy(
|
||||
Object.values(totalShares),
|
||||
(shares) => shares ** 2
|
||||
)
|
||||
const probs = _.range(0, bucketCount).map(
|
||||
const probs = range(0, bucketCount).map(
|
||||
(i) => totalShares[i] ** 2 / totalShareSum
|
||||
)
|
||||
|
||||
const values = _.range(0, bucketCount).map(
|
||||
const values = range(0, bucketCount).map(
|
||||
(i) =>
|
||||
// use mid point within bucket
|
||||
0.5 * (min + (i / bucketCount) * (max - min)) +
|
||||
0.5 * (min + ((i + 1) / bucketCount) * (max - min))
|
||||
)
|
||||
|
||||
const weightedValues = _.range(0, bucketCount).map(
|
||||
(i) => probs[i] * values[i]
|
||||
)
|
||||
const weightedValues = range(0, bucketCount).map((i) => probs[i] * values[i])
|
||||
|
||||
const expectation = _.sum(weightedValues)
|
||||
const expectation = sum(weightedValues)
|
||||
const rounded = Math.round(expectation * 1e2) / 1e2
|
||||
return rounded
|
||||
}
|
||||
|
@ -150,7 +147,7 @@ export function calculateDpmShares(
|
|||
bet: number,
|
||||
betChoice: string
|
||||
) {
|
||||
const squareSum = _.sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
const squareSum = sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
const shares = totalShares[betChoice] ?? 0
|
||||
|
||||
const c = 2 * bet * Math.sqrt(squareSum)
|
||||
|
@ -166,9 +163,9 @@ export function calculateNumericDpmShares(
|
|||
) {
|
||||
const shares: number[] = []
|
||||
|
||||
totalShares = _.cloneDeep(totalShares)
|
||||
totalShares = cloneDeep(totalShares)
|
||||
|
||||
const order = _.sortBy(
|
||||
const order = sortBy(
|
||||
bets.map(([, amount], i) => [amount, i]),
|
||||
([amount]) => amount
|
||||
).map(([, i]) => i)
|
||||
|
@ -190,11 +187,11 @@ export function calculateDpmRawShareValue(
|
|||
betChoice: string
|
||||
) {
|
||||
const currentValue = Math.sqrt(
|
||||
_.sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
sumBy(Object.values(totalShares), (shares) => shares ** 2)
|
||||
)
|
||||
|
||||
const postSaleValue = Math.sqrt(
|
||||
_.sumBy(Object.keys(totalShares), (outcome) =>
|
||||
sumBy(Object.keys(totalShares), (outcome) =>
|
||||
outcome === betChoice
|
||||
? Math.max(0, totalShares[outcome] - shares) ** 2
|
||||
: totalShares[outcome] ** 2
|
||||
|
@ -214,12 +211,12 @@ export function calculateDpmMoneyRatio(
|
|||
|
||||
const p = getDpmOutcomeProbability(totalShares, outcome)
|
||||
|
||||
const actual = _.sum(Object.values(pool)) - shareValue
|
||||
const actual = sum(Object.values(pool)) - shareValue
|
||||
|
||||
const betAmount = p * amount
|
||||
|
||||
const expected =
|
||||
_.sumBy(
|
||||
sumBy(
|
||||
Object.keys(totalBets),
|
||||
(outcome) =>
|
||||
getDpmOutcomeProbability(totalShares, outcome) *
|
||||
|
@ -271,8 +268,8 @@ export function calculateDpmCancelPayout(
|
|||
bet: Bet
|
||||
) {
|
||||
const { totalBets, pool } = contract
|
||||
const betTotal = _.sum(Object.values(totalBets))
|
||||
const poolTotal = _.sum(Object.values(pool))
|
||||
const betTotal = sum(Object.values(totalBets))
|
||||
const poolTotal = sum(Object.values(pool))
|
||||
|
||||
return (bet.amount / betTotal) * poolTotal
|
||||
}
|
||||
|
@ -295,7 +292,7 @@ export function calculateStandardDpmPayout(
|
|||
const { totalShares, phantomShares, pool } = contract
|
||||
if (!totalShares[outcome]) return 0
|
||||
|
||||
const poolTotal = _.sum(Object.values(pool))
|
||||
const poolTotal = sum(Object.values(pool))
|
||||
|
||||
const total =
|
||||
totalShares[outcome] - (phantomShares ? phantomShares[outcome] : 0)
|
||||
|
@ -356,19 +353,19 @@ function calculateMktDpmPayout(
|
|||
let probs: { [outcome: string]: number }
|
||||
|
||||
if (resolutions) {
|
||||
const probTotal = _.sum(Object.values(resolutions))
|
||||
probs = _.mapValues(
|
||||
const probTotal = sum(Object.values(resolutions))
|
||||
probs = mapValues(
|
||||
totalShares,
|
||||
(_, outcome) => (resolutions[outcome] ?? 0) / probTotal
|
||||
)
|
||||
} else {
|
||||
const squareSum = _.sum(
|
||||
const squareSum = sum(
|
||||
Object.values(totalShares).map((shares) => shares ** 2)
|
||||
)
|
||||
probs = _.mapValues(totalShares, (shares) => shares ** 2 / squareSum)
|
||||
probs = mapValues(totalShares, (shares) => shares ** 2 / squareSum)
|
||||
}
|
||||
|
||||
const weightedShareTotal = _.sumBy(Object.keys(totalShares), (outcome) => {
|
||||
const weightedShareTotal = sumBy(Object.keys(totalShares), (outcome) => {
|
||||
return probs[outcome] * totalShares[outcome]
|
||||
})
|
||||
|
||||
|
@ -376,7 +373,7 @@ function calculateMktDpmPayout(
|
|||
|
||||
const poolFrac =
|
||||
outcomeType === 'NUMERIC'
|
||||
? _.sumBy(
|
||||
? sumBy(
|
||||
Object.keys((bet as NumericBet).allOutcomeShares ?? {}),
|
||||
(outcome) => {
|
||||
return (
|
||||
|
@ -387,7 +384,7 @@ function calculateMktDpmPayout(
|
|||
)
|
||||
: (probs[outcome] * shares) / weightedShareTotal
|
||||
|
||||
const totalPool = _.sum(Object.values(pool))
|
||||
const totalPool = sum(Object.values(pool))
|
||||
const winnings = poolFrac * totalPool
|
||||
return deductDpmFees(amount, winnings)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { maxBy } from 'lodash'
|
||||
import { Bet } from './bet'
|
||||
import {
|
||||
calculateCpmmSale,
|
||||
|
@ -180,7 +180,7 @@ export function getContractBetNullMetrics() {
|
|||
|
||||
export function getTopAnswer(contract: FreeResponseContract) {
|
||||
const { answers } = contract
|
||||
const top = _.maxBy(
|
||||
const top = maxBy(
|
||||
answers?.map((answer) => ({
|
||||
answer,
|
||||
prob: getOutcomeProbability(contract, answer.id),
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as _ from 'lodash'
|
||||
import { Answer } from './answer'
|
||||
import { Fees } from './fees'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { sumBy } from 'lodash'
|
||||
|
||||
import { Bet, MAX_LOAN_PER_CONTRACT, NumericBet } from './bet'
|
||||
import {
|
||||
|
@ -210,7 +210,7 @@ export const getNumericBetsInfo = (
|
|||
|
||||
export const getLoanAmount = (yourBets: Bet[], newBetAmount: number) => {
|
||||
const openBets = yourBets.filter((bet) => !bet.isSold && !bet.sale)
|
||||
const prevLoanAmount = _.sumBy(openBets, (bet) => bet.loanAmount ?? 0)
|
||||
const prevLoanAmount = sumBy(openBets, (bet) => bet.loanAmount ?? 0)
|
||||
const loanAmount = Math.min(
|
||||
newBetAmount,
|
||||
MAX_LOAN_PER_CONTRACT - prevLoanAmount
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { range } from 'lodash'
|
||||
import { PHANTOM_ANTE } from './antes'
|
||||
import {
|
||||
Binary,
|
||||
|
@ -131,7 +130,7 @@ const getNumericProps = (
|
|||
min: number,
|
||||
max: number
|
||||
) => {
|
||||
const buckets = _.range(0, bucketCount).map((i) => i.toString())
|
||||
const buckets = range(0, bucketCount).map((i) => i.toString())
|
||||
|
||||
const betAnte = ante / bucketCount
|
||||
const pool = Object.fromEntries(buckets.map((answer) => [answer, betAnte]))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {},
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { sum, groupBy, sumBy, mapValues } from 'lodash'
|
||||
|
||||
import { Bet, NumericBet } from './bet'
|
||||
import { deductDpmFees, getDpmProbability } from './calculate-dpm'
|
||||
|
@ -17,10 +17,10 @@ export const getDpmCancelPayouts = (
|
|||
bets: Bet[]
|
||||
) => {
|
||||
const { pool } = contract
|
||||
const poolTotal = _.sum(Object.values(pool))
|
||||
const poolTotal = sum(Object.values(pool))
|
||||
console.log('resolved N/A, pool M$', poolTotal)
|
||||
|
||||
const betSum = _.sumBy(bets, (b) => b.amount)
|
||||
const betSum = sumBy(bets, (b) => b.amount)
|
||||
|
||||
const payouts = bets.map((bet) => ({
|
||||
userId: bet.userId,
|
||||
|
@ -42,8 +42,8 @@ export const getDpmStandardPayouts = (
|
|||
) => {
|
||||
const winningBets = bets.filter((bet) => bet.outcome === outcome)
|
||||
|
||||
const poolTotal = _.sum(Object.values(contract.pool))
|
||||
const totalShares = _.sumBy(winningBets, (b) => b.shares)
|
||||
const poolTotal = sum(Object.values(contract.pool))
|
||||
const totalShares = sumBy(winningBets, (b) => b.shares)
|
||||
|
||||
const payouts = winningBets.map(({ userId, amount, shares }) => {
|
||||
const winnings = (shares / totalShares) * poolTotal
|
||||
|
@ -54,7 +54,7 @@ export const getDpmStandardPayouts = (
|
|||
return { userId, profit, payout }
|
||||
})
|
||||
|
||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
const profits = sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
const creatorFee = DPM_CREATOR_FEE * profits
|
||||
const platformFee = DPM_PLATFORM_FEE * profits
|
||||
|
||||
|
@ -93,10 +93,10 @@ export const getNumericDpmPayouts = (
|
|||
contract: FullContract<DPM, any>,
|
||||
bets: NumericBet[]
|
||||
) => {
|
||||
const totalShares = _.sumBy(bets, (bet) => bet.allOutcomeShares[outcome] ?? 0)
|
||||
const totalShares = sumBy(bets, (bet) => bet.allOutcomeShares[outcome] ?? 0)
|
||||
const winningBets = bets.filter((bet) => !!bet.allOutcomeShares[outcome])
|
||||
|
||||
const poolTotal = _.sum(Object.values(contract.pool))
|
||||
const poolTotal = sum(Object.values(contract.pool))
|
||||
|
||||
const payouts = winningBets.map(
|
||||
({ userId, allBetAmounts, allOutcomeShares }) => {
|
||||
|
@ -112,7 +112,7 @@ export const getNumericDpmPayouts = (
|
|||
}
|
||||
)
|
||||
|
||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
const profits = sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
const creatorFee = DPM_CREATOR_FEE * profits
|
||||
const platformFee = DPM_PLATFORM_FEE * profits
|
||||
|
||||
|
@ -156,7 +156,7 @@ export const getDpmMktPayouts = (
|
|||
? getDpmProbability(contract.totalShares)
|
||||
: resolutionProbability
|
||||
|
||||
const weightedShareTotal = _.sumBy(bets, (b) =>
|
||||
const weightedShareTotal = sumBy(bets, (b) =>
|
||||
b.outcome === 'YES' ? p * b.shares : (1 - p) * b.shares
|
||||
)
|
||||
|
||||
|
@ -170,7 +170,7 @@ export const getDpmMktPayouts = (
|
|||
return { userId, profit, payout }
|
||||
})
|
||||
|
||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
const profits = sumBy(payouts, (po) => Math.max(0, po.profit))
|
||||
|
||||
const creatorFee = DPM_CREATOR_FEE * profits
|
||||
const platformFee = DPM_PLATFORM_FEE * profits
|
||||
|
@ -210,15 +210,15 @@ export const getPayoutsMultiOutcome = (
|
|||
contract: FullContract<DPM, Multi | FreeResponse>,
|
||||
bets: Bet[]
|
||||
) => {
|
||||
const poolTotal = _.sum(Object.values(contract.pool))
|
||||
const poolTotal = sum(Object.values(contract.pool))
|
||||
const winningBets = bets.filter((bet) => resolutions[bet.outcome])
|
||||
|
||||
const betsByOutcome = _.groupBy(winningBets, (bet) => bet.outcome)
|
||||
const sharesByOutcome = _.mapValues(betsByOutcome, (bets) =>
|
||||
_.sumBy(bets, (bet) => bet.shares)
|
||||
const betsByOutcome = groupBy(winningBets, (bet) => bet.outcome)
|
||||
const sharesByOutcome = mapValues(betsByOutcome, (bets) =>
|
||||
sumBy(bets, (bet) => bet.shares)
|
||||
)
|
||||
|
||||
const probTotal = _.sum(Object.values(resolutions))
|
||||
const probTotal = sum(Object.values(resolutions))
|
||||
|
||||
const payouts = winningBets.map(({ userId, outcome, amount, shares }) => {
|
||||
const prob = resolutions[outcome] / probTotal
|
||||
|
@ -229,7 +229,7 @@ export const getPayoutsMultiOutcome = (
|
|||
return { userId, profit, payout }
|
||||
})
|
||||
|
||||
const profits = _.sumBy(payouts, (po) => po.profit)
|
||||
const profits = sumBy(payouts, (po) => po.profit)
|
||||
|
||||
const creatorFee = DPM_CREATOR_FEE * profits
|
||||
const platformFee = DPM_PLATFORM_FEE * profits
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { sum } from 'lodash'
|
||||
|
||||
import { Bet } from './bet'
|
||||
import { getProbability } from './calculate'
|
||||
|
@ -50,7 +50,7 @@ export const getStandardFixedPayouts = (
|
|||
'pool',
|
||||
contract.pool[outcome],
|
||||
'payouts',
|
||||
_.sum(payouts),
|
||||
sum(payouts),
|
||||
'creator fee',
|
||||
creatorPayout
|
||||
)
|
||||
|
@ -105,7 +105,7 @@ export const getMktFixedPayouts = (
|
|||
'pool',
|
||||
p * contract.pool.YES + (1 - p) * contract.pool.NO,
|
||||
'payouts',
|
||||
_.sum(payouts),
|
||||
sum(payouts),
|
||||
'creator fee',
|
||||
creatorPayout
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { sumBy, groupBy, mapValues } from 'lodash'
|
||||
|
||||
import { Bet, NumericBet } from './bet'
|
||||
import {
|
||||
|
@ -32,16 +32,19 @@ export type Payout = {
|
|||
|
||||
export const getLoanPayouts = (bets: Bet[]): Payout[] => {
|
||||
const betsWithLoans = bets.filter((bet) => bet.loanAmount)
|
||||
const betsByUser = _.groupBy(betsWithLoans, (bet) => bet.userId)
|
||||
const loansByUser = _.mapValues(betsByUser, (bets) =>
|
||||
_.sumBy(bets, (bet) => -(bet.loanAmount ?? 0))
|
||||
const betsByUser = groupBy(betsWithLoans, (bet) => bet.userId)
|
||||
const loansByUser = mapValues(betsByUser, (bets) =>
|
||||
sumBy(bets, (bet) => -(bet.loanAmount ?? 0))
|
||||
)
|
||||
return _.toPairs(loansByUser).map(([userId, payout]) => ({ userId, payout }))
|
||||
return Object.entries(loansByUser).map(([userId, payout]) => ({
|
||||
userId,
|
||||
payout,
|
||||
}))
|
||||
}
|
||||
|
||||
export const groupPayoutsByUser = (payouts: Payout[]) => {
|
||||
const groups = _.groupBy(payouts, (payout) => payout.userId)
|
||||
return _.mapValues(groups, (group) => _.sumBy(group, (g) => g.payout))
|
||||
const groups = groupBy(payouts, (payout) => payout.userId)
|
||||
return mapValues(groups, (group) => sumBy(group, (g) => g.payout))
|
||||
}
|
||||
|
||||
export type PayoutInfo = {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { union, sum, sumBy, sortBy, groupBy, mapValues } from 'lodash'
|
||||
import { Bet } from './bet'
|
||||
import { Contract } from './contract'
|
||||
import { ClickEvent } from './tracking'
|
||||
|
@ -21,13 +21,13 @@ export const getRecommendedContracts = (
|
|||
|
||||
const yourWordFrequency = contractsToWordFrequency(yourContracts)
|
||||
const otherWordFrequency = contractsToWordFrequency(notYourContracts)
|
||||
const words = _.union(
|
||||
const words = union(
|
||||
Object.keys(yourWordFrequency),
|
||||
Object.keys(otherWordFrequency)
|
||||
)
|
||||
|
||||
const yourWeightedFrequency = _.fromPairs(
|
||||
_.map(words, (word) => {
|
||||
const yourWeightedFrequency = Object.fromEntries(
|
||||
words.map((word) => {
|
||||
const [yourFreq, otherFreq] = [
|
||||
yourWordFrequency[word] ?? 0,
|
||||
otherWordFrequency[word] ?? 0,
|
||||
|
@ -47,7 +47,7 @@ export const getRecommendedContracts = (
|
|||
const scoredContracts = contracts.map((contract) => {
|
||||
const wordFrequency = contractToWordFrequency(contract)
|
||||
|
||||
const score = _.sumBy(Object.keys(wordFrequency), (word) => {
|
||||
const score = sumBy(Object.keys(wordFrequency), (word) => {
|
||||
const wordFreq = wordFrequency[word] ?? 0
|
||||
const weight = yourWeightedFrequency[word] ?? 0
|
||||
return wordFreq * weight
|
||||
|
@ -59,7 +59,7 @@ export const getRecommendedContracts = (
|
|||
}
|
||||
})
|
||||
|
||||
return _.sortBy(scoredContracts, (scored) => -scored.score).map(
|
||||
return sortBy(scoredContracts, (scored) => -scored.score).map(
|
||||
(scored) => scored.contract
|
||||
)
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ const getWordsCount = (text: string) => {
|
|||
}
|
||||
|
||||
const toFrequency = (counts: { [word: string]: number }) => {
|
||||
const total = _.sum(Object.values(counts))
|
||||
return _.mapValues(counts, (count) => count / total)
|
||||
const total = sum(Object.values(counts))
|
||||
return mapValues(counts, (count) => count / total)
|
||||
}
|
||||
|
||||
const contractToWordFrequency = (contract: Contract) =>
|
||||
|
@ -108,8 +108,8 @@ export const getWordScores = (
|
|||
clicks: ClickEvent[],
|
||||
bets: Bet[]
|
||||
) => {
|
||||
const contractClicks = _.groupBy(clicks, (click) => click.contractId)
|
||||
const contractBets = _.groupBy(bets, (bet) => bet.contractId)
|
||||
const contractClicks = groupBy(clicks, (click) => click.contractId)
|
||||
const contractBets = groupBy(bets, (bet) => bet.contractId)
|
||||
|
||||
const yourContracts = contracts.filter(
|
||||
(c) =>
|
||||
|
@ -117,25 +117,22 @@ export const getWordScores = (
|
|||
)
|
||||
const yourTfIdf = calculateContractTfIdf(yourContracts)
|
||||
|
||||
const contractWordScores = _.mapValues(
|
||||
yourTfIdf,
|
||||
(wordsTfIdf, contractId) => {
|
||||
const viewCount = contractViewCounts[contractId] ?? 0
|
||||
const clickCount = contractClicks[contractId]?.length ?? 0
|
||||
const betCount = contractBets[contractId]?.length ?? 0
|
||||
const contractWordScores = mapValues(yourTfIdf, (wordsTfIdf, contractId) => {
|
||||
const viewCount = contractViewCounts[contractId] ?? 0
|
||||
const clickCount = contractClicks[contractId]?.length ?? 0
|
||||
const betCount = contractBets[contractId]?.length ?? 0
|
||||
|
||||
const factor =
|
||||
-1 * Math.log(viewCount + 1) +
|
||||
10 * Math.log(betCount + clickCount / 4 + 1)
|
||||
const factor =
|
||||
-1 * Math.log(viewCount + 1) +
|
||||
10 * Math.log(betCount + clickCount / 4 + 1)
|
||||
|
||||
return _.mapValues(wordsTfIdf, (tfIdf) => tfIdf * factor)
|
||||
}
|
||||
)
|
||||
return mapValues(wordsTfIdf, (tfIdf) => tfIdf * factor)
|
||||
})
|
||||
|
||||
const wordScores = Object.values(contractWordScores).reduce(addObjects, {})
|
||||
const minScore = Math.min(...Object.values(wordScores))
|
||||
const maxScore = Math.max(...Object.values(wordScores))
|
||||
const normalizedWordScores = _.mapValues(
|
||||
const normalizedWordScores = mapValues(
|
||||
wordScores,
|
||||
(score) => (score - minScore) / (maxScore - minScore)
|
||||
)
|
||||
|
@ -156,7 +153,7 @@ export function getContractScore(
|
|||
if (Object.keys(wordScores).length === 0) return 1
|
||||
|
||||
const wordFrequency = contractToWordFrequency(contract)
|
||||
const score = _.sumBy(Object.keys(wordFrequency), (word) => {
|
||||
const score = sumBy(Object.keys(wordFrequency), (word) => {
|
||||
const wordFreq = wordFrequency[word] ?? 0
|
||||
const weight = wordScores[word] ?? 0
|
||||
return wordFreq * weight
|
||||
|
@ -178,11 +175,13 @@ function calculateContractTfIdf(contracts: Contract[]) {
|
|||
}
|
||||
}
|
||||
|
||||
const wordIdf = _.mapValues(wordsCount, (count) =>
|
||||
const wordIdf = mapValues(wordsCount, (count) =>
|
||||
Math.log(contracts.length / count)
|
||||
)
|
||||
const contractWordsTfIdf = _.map(contractFreq, (wordFreq) =>
|
||||
_.mapValues(wordFreq, (freq, word) => freq * wordIdf[word])
|
||||
const contractWordsTfIdf = contractFreq.map((wordFreq) =>
|
||||
mapValues(wordFreq, (freq, word) => freq * wordIdf[word])
|
||||
)
|
||||
return Object.fromEntries(
|
||||
contracts.map((c, i) => [c.id, contractWordsTfIdf[i]])
|
||||
)
|
||||
return _.fromPairs(contracts.map((c, i) => [c.id, contractWordsTfIdf[i]]))
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import * as _ from 'lodash'
|
||||
import { groupBy, sumBy, mapValues, partition } from 'lodash'
|
||||
|
||||
import { Bet } from './bet'
|
||||
import { Binary, Contract, FullContract } from './contract'
|
||||
import { getPayouts } from './payouts'
|
||||
|
||||
export function scoreCreators(contracts: Contract[], bets: Bet[][]) {
|
||||
const creatorScore = _.mapValues(
|
||||
_.groupBy(contracts, ({ creatorId }) => creatorId),
|
||||
(contracts) => _.sumBy(contracts, ({ pool }) => pool.YES + pool.NO)
|
||||
const creatorScore = mapValues(
|
||||
groupBy(contracts, ({ creatorId }) => creatorId),
|
||||
(contracts) => sumBy(contracts, ({ pool }) => pool.YES + pool.NO)
|
||||
)
|
||||
|
||||
return creatorScore
|
||||
|
@ -30,7 +30,7 @@ export function scoreUsersByContract(
|
|||
) {
|
||||
const { resolution, resolutionProbability } = contract
|
||||
|
||||
const [closedBets, openBets] = _.partition(
|
||||
const [closedBets, openBets] = partition(
|
||||
bets,
|
||||
(bet) => bet.isSold || bet.sale
|
||||
)
|
||||
|
@ -58,9 +58,9 @@ export function scoreUsersByContract(
|
|||
|
||||
const netPayouts = [...resolvePayouts, ...salePayouts, ...investments]
|
||||
|
||||
const userScore = _.mapValues(
|
||||
_.groupBy(netPayouts, (payout) => payout.userId),
|
||||
(payouts) => _.sumBy(payouts, ({ payout }) => payout)
|
||||
const userScore = mapValues(
|
||||
groupBy(netPayouts, (payout) => payout.userId),
|
||||
(payouts) => sumBy(payouts, ({ payout }) => payout)
|
||||
)
|
||||
|
||||
return userScore
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { union } from 'lodash'
|
||||
|
||||
export const removeUndefinedProps = <T>(obj: T): T => {
|
||||
let newObj: any = {}
|
||||
|
@ -14,7 +14,7 @@ export const addObjects = <T extends { [key: string]: number }>(
|
|||
obj1: T,
|
||||
obj2: T
|
||||
) => {
|
||||
const keys = _.union(Object.keys(obj1), Object.keys(obj2))
|
||||
const keys = union(Object.keys(obj1), Object.keys(obj2))
|
||||
const newObj = {} as any
|
||||
|
||||
for (let key of keys) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
plugins: ['lodash'],
|
||||
extends: ['eslint:recommended'],
|
||||
ignorePatterns: ['lib'],
|
||||
env: {
|
||||
|
@ -17,5 +18,6 @@ module.exports = {
|
|||
rules: {
|
||||
'no-unused-vars': 'off',
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'lodash/import-scope': [2, 'member'],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { getUser } from './utils'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
@ -34,7 +33,7 @@ export const createFold = functions.runWith({ minInstances: 1 }).https.onCall(
|
|||
return { status: 'error', message: 'About must be a string' }
|
||||
about = about.trim().slice(0, 140)
|
||||
|
||||
if (!_.isArray(tags))
|
||||
if (!Array.isArray(tags))
|
||||
return { status: 'error', message: 'Tags must be an array of strings' }
|
||||
|
||||
console.log(
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import * as _ from 'lodash'
|
||||
|
||||
import { DOMAIN, PROJECT_ID } from '../../common/envs/constants'
|
||||
import { Answer } from '../../common/answer'
|
||||
import { Bet } from '../../common/bet'
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { getContract } from './utils'
|
||||
import { Bet } from '../../common/bet'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
import { getContract, getUser, getValues } from './utils'
|
||||
import { Comment } from '../../common/comment'
|
||||
|
@ -60,7 +60,7 @@ export const onCreateComment = functions.firestore
|
|||
firestore.collection('contracts').doc(contractId).collection('comments')
|
||||
)
|
||||
|
||||
const recipientUserIds = _.uniq([
|
||||
const recipientUserIds = uniq([
|
||||
contract.creatorId,
|
||||
...comments.map((comment) => comment.userId),
|
||||
]).filter((id) => id !== comment.userId)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { partition, sumBy } from 'lodash'
|
||||
|
||||
import { Bet } from '../../common/bet'
|
||||
import { getProbability } from '../../common/calculate'
|
||||
|
@ -25,14 +25,14 @@ export const redeemShares = async (userId: string, contractId: string) => {
|
|||
.where('userId', '==', userId)
|
||||
)
|
||||
const bets = betsSnap.docs.map((doc) => doc.data() as Bet)
|
||||
const [yesBets, noBets] = _.partition(bets, (b) => b.outcome === 'YES')
|
||||
const yesShares = _.sumBy(yesBets, (b) => b.shares)
|
||||
const noShares = _.sumBy(noBets, (b) => b.shares)
|
||||
const [yesBets, noBets] = partition(bets, (b) => b.outcome === 'YES')
|
||||
const yesShares = sumBy(yesBets, (b) => b.shares)
|
||||
const noShares = sumBy(noBets, (b) => b.shares)
|
||||
|
||||
const amount = Math.min(yesShares, noShares)
|
||||
if (amount <= 0) return
|
||||
|
||||
const prevLoanAmount = _.sumBy(bets, (bet) => bet.loanAmount ?? 0)
|
||||
const prevLoanAmount = sumBy(bets, (bet) => bet.loanAmount ?? 0)
|
||||
const loanPaid = Math.min(prevLoanAmount, amount)
|
||||
const netAmount = amount - loanPaid
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { difference, uniq, mapValues, groupBy, sumBy } from 'lodash'
|
||||
|
||||
import { Contract } from '../../common/contract'
|
||||
import { User } from '../../common/user'
|
||||
|
@ -187,13 +187,13 @@ const sendResolutionEmails = async (
|
|||
resolutionProbability?: number,
|
||||
resolutions?: { [outcome: string]: number }
|
||||
) => {
|
||||
const nonWinners = _.difference(
|
||||
_.uniq(openBets.map(({ userId }) => userId)),
|
||||
const nonWinners = difference(
|
||||
uniq(openBets.map(({ userId }) => userId)),
|
||||
Object.keys(userPayouts)
|
||||
)
|
||||
const investedByUser = _.mapValues(
|
||||
_.groupBy(openBets, (bet) => bet.userId),
|
||||
(bets) => _.sumBy(bets, (bet) => bet.amount)
|
||||
const investedByUser = mapValues(
|
||||
groupBy(openBets, (bet) => bet.userId),
|
||||
(bets) => sumBy(bets, (bet) => bet.amount)
|
||||
)
|
||||
const emailPayouts = [
|
||||
...Object.entries(userPayouts),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -20,7 +20,7 @@ async function migrateContract(
|
|||
.get()
|
||||
.then((snap) => snap.docs.map((bet) => bet.data() as Bet))
|
||||
|
||||
const lastBet = _.sortBy(bets, (bet) => -bet.createdTime)[0]
|
||||
const lastBet = sortBy(bets, (bet) => -bet.createdTime)[0]
|
||||
if (lastBet) {
|
||||
const probAfter = getDpmProbability(contract.totalShares)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import * as fs from 'fs'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -19,7 +19,7 @@ async function lowercaseFoldTags() {
|
|||
const foldRef = firestore.doc(`folds/${fold.id}`)
|
||||
|
||||
const { tags } = fold
|
||||
const lowercaseTags = _.uniq(tags.map((tag) => tag.toLowerCase()))
|
||||
const lowercaseTags = uniq(tags.map((tag) => tag.toLowerCase()))
|
||||
|
||||
console.log('Adding lowercase tags', fold.slug, lowercaseTags)
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sumBy } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -25,8 +25,8 @@ async function migrateContract(contractRef: DocRef, contract: Contract) {
|
|||
.then((snap) => snap.docs.map((bet) => bet.data() as Bet))
|
||||
|
||||
const totalShares = {
|
||||
YES: _.sumBy(bets, (bet) => (bet.outcome === 'YES' ? bet.shares : 0)),
|
||||
NO: _.sumBy(bets, (bet) => (bet.outcome === 'NO' ? bet.shares : 0)),
|
||||
YES: sumBy(bets, (bet) => (bet.outcome === 'YES' ? bet.shares : 0)),
|
||||
NO: sumBy(bets, (bet) => (bet.outcome === 'NO' ? bet.shares : 0)),
|
||||
}
|
||||
|
||||
await contractRef.update({ totalShares })
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -48,7 +48,7 @@ async function recalculateContract(contractRef: DocRef, isCommit = false) {
|
|||
|
||||
const betsRef = contractRef.collection('bets')
|
||||
const betDocs = await transaction.get(betsRef)
|
||||
const bets = _.sortBy(
|
||||
const bets = sortBy(
|
||||
betDocs.docs.map((d) => d.data() as Bet),
|
||||
(b) => b.createdTime
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sortBy, sumBy } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -35,7 +35,7 @@ async function recalculateContract(
|
|||
const contract = contractDoc.data() as FullContract<DPM, Binary>
|
||||
|
||||
const betDocs = await transaction.get(contractRef.collection('bets'))
|
||||
const bets = _.sortBy(
|
||||
const bets = sortBy(
|
||||
betDocs.docs.map((d) => d.data() as Bet),
|
||||
(b) => b.createdTime
|
||||
)
|
||||
|
@ -43,8 +43,8 @@ async function recalculateContract(
|
|||
const phantomAnte = startPool.YES + startPool.NO
|
||||
|
||||
const leftovers =
|
||||
_.sumBy(bets, (b) => b.amount) -
|
||||
_.sumBy(bets, (b) => {
|
||||
sumBy(bets, (b) => b.amount) -
|
||||
sumBy(bets, (b) => {
|
||||
if (!b.sale) return b.amount
|
||||
const soldBet = bets.find((bet) => bet.id === b.sale?.betId)
|
||||
return soldBet?.amount || 0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { flatten, groupBy, sumBy, mapValues } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -35,12 +35,12 @@ async function checkIfPayOutAgain(contractRef: DocRef, contract: Contract) {
|
|||
)
|
||||
|
||||
const loanPayouts = getLoanPayouts(openBets)
|
||||
const groups = _.groupBy(
|
||||
const groups = groupBy(
|
||||
[...payouts, ...loanPayouts],
|
||||
(payout) => payout.userId
|
||||
)
|
||||
const userPayouts = _.mapValues(groups, (group) =>
|
||||
_.sumBy(group, (g) => g.payout)
|
||||
const userPayouts = mapValues(groups, (group) =>
|
||||
sumBy(group, (g) => g.payout)
|
||||
)
|
||||
|
||||
const entries = Object.entries(userPayouts)
|
||||
|
@ -93,7 +93,7 @@ async function payOutContractAgain() {
|
|||
)
|
||||
)
|
||||
|
||||
const flattened = _.flatten(toPayOutAgain.map((d) => d.toBePaidOut))
|
||||
const flattened = flatten(toPayOutAgain.map((d) => d.toBePaidOut))
|
||||
|
||||
for (const [userId, payout] of flattened) {
|
||||
console.log('Paying out', userId, payout)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sumBy } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -20,13 +20,13 @@ async function recalculateContract(contractRef: DocRef, contract: Contract) {
|
|||
const openBets = bets.filter((b) => !b.isSold && !b.sale)
|
||||
|
||||
const totalShares = {
|
||||
YES: _.sumBy(openBets, (bet) => (bet.outcome === 'YES' ? bet.shares : 0)),
|
||||
NO: _.sumBy(openBets, (bet) => (bet.outcome === 'NO' ? bet.shares : 0)),
|
||||
YES: sumBy(openBets, (bet) => (bet.outcome === 'YES' ? bet.shares : 0)),
|
||||
NO: sumBy(openBets, (bet) => (bet.outcome === 'NO' ? bet.shares : 0)),
|
||||
}
|
||||
|
||||
const totalBets = {
|
||||
YES: _.sumBy(openBets, (bet) => (bet.outcome === 'YES' ? bet.amount : 0)),
|
||||
NO: _.sumBy(openBets, (bet) => (bet.outcome === 'NO' ? bet.amount : 0)),
|
||||
YES: sumBy(openBets, (bet) => (bet.outcome === 'YES' ? bet.amount : 0)),
|
||||
NO: sumBy(openBets, (bet) => (bet.outcome === 'NO' ? bet.amount : 0)),
|
||||
}
|
||||
|
||||
await contractRef.update({ totalShares, totalBets })
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
@ -19,7 +19,7 @@ async function updateContractTags() {
|
|||
for (const contract of contracts) {
|
||||
const contractRef = firestore.doc(`contracts/${contract.id}`)
|
||||
|
||||
const tags = _.uniq([
|
||||
const tags = uniq([
|
||||
...parseTags(contract.question + contract.description),
|
||||
...(contract.tags ?? []),
|
||||
])
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { initAdmin } from './script-init'
|
||||
initAdmin()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as _ from 'lodash'
|
||||
import { partition, sumBy } from 'lodash'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as functions from 'firebase-functions'
|
||||
|
||||
|
@ -51,15 +51,15 @@ export const sellShares = functions.runWith({ minInstances: 1 }).https.onCall(
|
|||
contractDoc.collection('bets').where('userId', '==', userId)
|
||||
)
|
||||
|
||||
const prevLoanAmount = _.sumBy(userBets, (bet) => bet.loanAmount ?? 0)
|
||||
const prevLoanAmount = sumBy(userBets, (bet) => bet.loanAmount ?? 0)
|
||||
|
||||
const [yesBets, noBets] = _.partition(
|
||||
const [yesBets, noBets] = partition(
|
||||
userBets ?? [],
|
||||
(bet) => bet.outcome === 'YES'
|
||||
)
|
||||
const [yesShares, noShares] = [
|
||||
_.sumBy(yesBets, (bet) => bet.shares),
|
||||
_.sumBy(noBets, (bet) => bet.shares),
|
||||
sumBy(yesBets, (bet) => bet.shares),
|
||||
sumBy(noBets, (bet) => bet.shares),
|
||||
]
|
||||
|
||||
const maxShares = outcome === 'YES' ? yesShares : noShares
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { getUser } from './utils'
|
||||
import { PrivateUser } from '../../common/user'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sumBy } from 'lodash'
|
||||
|
||||
import { getValues } from './utils'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
@ -39,5 +39,5 @@ const computeVolumeFrom = async (contract: Contract, timeAgoMs: number) => {
|
|||
.where('createdTime', '>', Date.now() - timeAgoMs)
|
||||
)
|
||||
|
||||
return _.sumBy(bets, (bet) => (bet.isRedemption ? 0 : Math.abs(bet.amount)))
|
||||
return sumBy(bets, (bet) => (bet.isRedemption ? 0 : Math.abs(bet.amount)))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as _ from 'lodash'
|
||||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import { shuffle, sortBy } from 'lodash'
|
||||
|
||||
import { getValue, getValues } from './utils'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
@ -30,7 +30,7 @@ const BATCH_SIZE = 30
|
|||
const MAX_BATCHES = 50
|
||||
|
||||
const getUserBatches = async () => {
|
||||
const users = _.shuffle(await getValues<User>(firestore.collection('users')))
|
||||
const users = shuffle(await getValues<User>(firestore.collection('users')))
|
||||
let userBatches: User[][] = []
|
||||
for (let i = 0; i < users.length; i += BATCH_SIZE) {
|
||||
userBatches.push(users.slice(i, i + BATCH_SIZE))
|
||||
|
@ -128,7 +128,7 @@ export const computeFeed = async (user: User, contracts: Contract[]) => {
|
|||
return [contract, score] as [Contract, number]
|
||||
})
|
||||
|
||||
const sortedContracts = _.sortBy(
|
||||
const sortedContracts = sortBy(
|
||||
scoredContracts,
|
||||
([_, score]) => score
|
||||
).reverse()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
|
||||
import { getValue, getValues } from './utils'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as functions from 'firebase-functions'
|
||||
import * as admin from 'firebase-admin'
|
||||
import * as _ from 'lodash'
|
||||
import { sum, sumBy } from 'lodash'
|
||||
|
||||
import { getValues } from './utils'
|
||||
import { Contract } from '../../common/contract'
|
||||
|
@ -19,7 +19,7 @@ export const updateUserMetrics = functions.pubsub
|
|||
getValues<Contract>(firestore.collection('contracts')),
|
||||
])
|
||||
|
||||
const contractsDict = _.fromPairs(
|
||||
const contractsDict = Object.fromEntries(
|
||||
contracts.map((contract) => [contract.id, contract])
|
||||
)
|
||||
|
||||
|
@ -43,12 +43,12 @@ export const updateUserMetrics = functions.pubsub
|
|||
|
||||
const computeInvestmentValue = async (
|
||||
user: User,
|
||||
contractsDict: _.Dictionary<Contract>
|
||||
contractsDict: { [k: string]: Contract }
|
||||
) => {
|
||||
const query = firestore.collectionGroup('bets').where('userId', '==', user.id)
|
||||
const bets = await getValues<Bet>(query)
|
||||
|
||||
return _.sumBy(bets, (bet) => {
|
||||
return sumBy(bets, (bet) => {
|
||||
const contract = contractsDict[bet.contractId]
|
||||
if (!contract || contract.isResolved) return 0
|
||||
if (bet.sale || bet.isSold) return 0
|
||||
|
@ -60,20 +60,20 @@ const computeInvestmentValue = async (
|
|||
|
||||
const computeTotalPool = async (
|
||||
user: User,
|
||||
contractsDict: _.Dictionary<Contract>
|
||||
contractsDict: { [k: string]: Contract }
|
||||
) => {
|
||||
const creatorContracts = Object.values(contractsDict).filter(
|
||||
(contract) => contract.creatorId === user.id
|
||||
)
|
||||
const pools = creatorContracts.map((contract) =>
|
||||
_.sum(Object.values(contract.pool))
|
||||
sum(Object.values(contract.pool))
|
||||
)
|
||||
return _.sum(pools)
|
||||
return sum(pools)
|
||||
}
|
||||
|
||||
const computeVolume = async (contract: Contract) => {
|
||||
const bets = await getValues<Bet>(
|
||||
firestore.collection(`contracts/${contract.id}/bets`)
|
||||
)
|
||||
return _.sumBy(bets, (bet) => Math.abs(bet.amount))
|
||||
return sumBy(bets, (bet) => Math.abs(bet.amount))
|
||||
}
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
"scripts": {},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "4.6.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.25.0",
|
||||
"@typescript-eslint/parser": "5.25.0",
|
||||
"eslint": "8.15.0",
|
||||
"prettier": "2.5.0"
|
||||
"eslint-plugin-lodash": "^7.4.0",
|
||||
"prettier": "2.5.0",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['lodash'],
|
||||
extends: ['plugin:react-hooks/recommended', 'plugin:@next/next/recommended'],
|
||||
rules: {
|
||||
// Add or disable rules here.
|
||||
'@next/next/no-img-element': 'off',
|
||||
'@next/next/no-typos': 'off',
|
||||
'lodash/import-scope': [2, 'member'],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Point, ResponsiveLine } from '@nivo/line'
|
||||
import dayjs from 'dayjs'
|
||||
import _ from 'lodash'
|
||||
import { zip } from 'lodash'
|
||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||
import { Col } from '../layout/col'
|
||||
|
||||
|
@ -16,7 +16,7 @@ export function DailyCountChart(props: {
|
|||
dayjs(startDate).add(i, 'day').toDate()
|
||||
)
|
||||
|
||||
const points = _.zip(dates, dailyCounts).map(([date, betCount]) => ({
|
||||
const points = zip(dates, dailyCounts).map(([date, betCount]) => ({
|
||||
x: date,
|
||||
y: betCount,
|
||||
}))
|
||||
|
@ -68,7 +68,7 @@ export function DailyPercentChart(props: {
|
|||
dayjs(startDate).add(i, 'day').toDate()
|
||||
)
|
||||
|
||||
const points = _.zip(dates, dailyPercent).map(([date, betCount]) => ({
|
||||
const points = zip(dates, dailyPercent).map(([date, betCount]) => ({
|
||||
x: date,
|
||||
y: betCount,
|
||||
}))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import { sum, mapValues } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { DPM, FreeResponse, FullContract } from 'common/contract'
|
||||
|
@ -30,8 +30,8 @@ export function AnswerResolvePanel(props: {
|
|||
|
||||
setIsSubmitting(true)
|
||||
|
||||
const totalProb = _.sum(Object.values(chosenAnswers))
|
||||
const normalizedProbs = _.mapValues(
|
||||
const totalProb = sum(Object.values(chosenAnswers))
|
||||
const normalizedProbs = mapValues(
|
||||
chosenAnswers,
|
||||
(prob) => (100 * prob) / totalProb
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DatumValue } from '@nivo/core'
|
||||
import { ResponsiveLine } from '@nivo/line'
|
||||
import dayjs from 'dayjs'
|
||||
import _ from 'lodash'
|
||||
import { groupBy, sortBy, sumBy } from 'lodash'
|
||||
import { memo } from 'react'
|
||||
|
||||
import { Bet } from 'common/bet'
|
||||
|
@ -48,7 +48,7 @@ export const AnswersGraph = memo(function AnswersGraph(props: {
|
|||
// to the right.
|
||||
latestTime.add(1, 'month').valueOf()
|
||||
|
||||
const times = _.sortBy([
|
||||
const times = sortBy([
|
||||
createdTime,
|
||||
...bets.map((bet) => bet.createdTime),
|
||||
endTime,
|
||||
|
@ -167,7 +167,7 @@ const computeProbsByOutcome = (
|
|||
) => {
|
||||
const { totalBets } = contract
|
||||
|
||||
const betsByOutcome = _.groupBy(bets, (bet) => bet.outcome)
|
||||
const betsByOutcome = groupBy(bets, (bet) => bet.outcome)
|
||||
const outcomes = Object.keys(betsByOutcome).filter((outcome) => {
|
||||
const maxProb = Math.max(
|
||||
...betsByOutcome[outcome].map((bet) => bet.probAfter)
|
||||
|
@ -175,15 +175,15 @@ const computeProbsByOutcome = (
|
|||
return outcome !== '0' && maxProb > 0.02 && totalBets[outcome] > 0.000000001
|
||||
})
|
||||
|
||||
const trackedOutcomes = _.sortBy(
|
||||
const trackedOutcomes = sortBy(
|
||||
outcomes,
|
||||
(outcome) => -1 * getOutcomeProbability(contract, outcome)
|
||||
).slice(0, NUM_LINES)
|
||||
|
||||
const probsByOutcome = _.fromPairs(
|
||||
const probsByOutcome = Object.fromEntries(
|
||||
trackedOutcomes.map((outcome) => [outcome, [] as number[]])
|
||||
)
|
||||
const sharesByOutcome = _.fromPairs(
|
||||
const sharesByOutcome = Object.fromEntries(
|
||||
Object.keys(betsByOutcome).map((outcome) => [outcome, 0])
|
||||
)
|
||||
|
||||
|
@ -191,7 +191,7 @@ const computeProbsByOutcome = (
|
|||
const { outcome, shares } = bet
|
||||
sharesByOutcome[outcome] += shares
|
||||
|
||||
const sharesSquared = _.sumBy(
|
||||
const sharesSquared = sumBy(
|
||||
Object.values(sharesByOutcome).map((shares) => shares ** 2)
|
||||
)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash'
|
||||
import React, { useLayoutEffect, useState } from 'react'
|
||||
import { sortBy, partition, sum, uniq } from 'lodash'
|
||||
import { useLayoutEffect, useState } from 'react'
|
||||
|
||||
import { DPM, FreeResponse, FullContract } from 'common/contract'
|
||||
import { Col } from '../layout/col'
|
||||
|
@ -32,7 +32,7 @@ export function AnswersPanel(props: {
|
|||
const { creatorId, resolution, resolutions, totalBets } = contract
|
||||
|
||||
const answers = useAnswers(contract.id) ?? contract.answers
|
||||
const [winningAnswers, losingAnswers] = _.partition(
|
||||
const [winningAnswers, losingAnswers] = partition(
|
||||
answers.filter(
|
||||
(answer) => answer.id !== '0' && totalBets[answer.id] > 0.000000001
|
||||
),
|
||||
|
@ -40,10 +40,10 @@ export function AnswersPanel(props: {
|
|||
answer.id === resolution || (resolutions && resolutions[answer.id])
|
||||
)
|
||||
const sortedAnswers = [
|
||||
..._.sortBy(winningAnswers, (answer) =>
|
||||
...sortBy(winningAnswers, (answer) =>
|
||||
resolutions ? -1 * resolutions[answer.id] : 0
|
||||
),
|
||||
..._.sortBy(
|
||||
...sortBy(
|
||||
resolution ? [] : losingAnswers,
|
||||
(answer) => -1 * getDpmOutcomeProbability(contract.totalShares, answer.id)
|
||||
),
|
||||
|
@ -58,7 +58,7 @@ export function AnswersPanel(props: {
|
|||
[answerId: string]: number
|
||||
}>({})
|
||||
|
||||
const chosenTotal = _.sum(Object.values(chosenAnswers))
|
||||
const chosenTotal = sum(Object.values(chosenAnswers))
|
||||
|
||||
const answerItems = getAnswerItems(
|
||||
contract,
|
||||
|
@ -158,10 +158,10 @@ function getAnswerItems(
|
|||
answers: Answer[],
|
||||
user: User | undefined | null
|
||||
) {
|
||||
let outcomes = _.uniq(
|
||||
answers.map((answer) => answer.number.toString())
|
||||
).filter((outcome) => getOutcomeProbability(contract, outcome) > 0.0001)
|
||||
outcomes = _.sortBy(outcomes, (outcome) =>
|
||||
let outcomes = uniq(answers.map((answer) => answer.number.toString())).filter(
|
||||
(outcome) => getOutcomeProbability(contract, outcome) > 0.0001
|
||||
)
|
||||
outcomes = sortBy(outcomes, (outcome) =>
|
||||
getOutcomeProbability(contract, outcome)
|
||||
).reverse()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { partition, sumBy } from 'lodash'
|
||||
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { Binary, CPMM, DPM, FullContract } from 'common/contract'
|
||||
|
@ -441,13 +441,13 @@ export function SellPanel(props: {
|
|||
const resultProb = getCpmmProbability(newPool, contract.p)
|
||||
|
||||
const openUserBets = userBets.filter((bet) => !bet.isSold && !bet.sale)
|
||||
const [yesBets, noBets] = _.partition(
|
||||
const [yesBets, noBets] = partition(
|
||||
openUserBets,
|
||||
(bet) => bet.outcome === 'YES'
|
||||
)
|
||||
const [yesShares, noShares] = [
|
||||
_.sumBy(yesBets, (bet) => bet.shares),
|
||||
_.sumBy(noBets, (bet) => bet.shares),
|
||||
sumBy(yesBets, (bet) => bet.shares),
|
||||
sumBy(noBets, (bet) => bet.shares),
|
||||
]
|
||||
|
||||
const sellOutcome = yesShares ? 'YES' : noShares ? 'NO' : undefined
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
import Link from 'next/link'
|
||||
import _ from 'lodash'
|
||||
import {
|
||||
uniq,
|
||||
groupBy,
|
||||
mapValues,
|
||||
sortBy,
|
||||
partition,
|
||||
sumBy,
|
||||
throttle,
|
||||
} from 'lodash'
|
||||
import dayjs from 'dayjs'
|
||||
import { useEffect, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
|
@ -54,7 +62,7 @@ export function BetsList(props: { user: User }) {
|
|||
|
||||
useEffect(() => {
|
||||
if (bets) {
|
||||
const contractIds = _.uniq(bets.map((bet) => bet.contractId))
|
||||
const contractIds = uniq(bets.map((bet) => bet.contractId))
|
||||
|
||||
let disposed = false
|
||||
Promise.all(contractIds.map((id) => getContractFromId(id))).then(
|
||||
|
@ -84,10 +92,10 @@ export function BetsList(props: { user: User }) {
|
|||
if (bets.length === 0) return <NoBets />
|
||||
// Decending creation time.
|
||||
bets.sort((bet1, bet2) => bet2.createdTime - bet1.createdTime)
|
||||
const contractBets = _.groupBy(bets, 'contractId')
|
||||
const contractsById = _.fromPairs(contracts.map((c) => [c.id, c]))
|
||||
const contractBets = groupBy(bets, 'contractId')
|
||||
const contractsById = Object.fromEntries(contracts.map((c) => [c.id, c]))
|
||||
|
||||
const contractsMetrics = _.mapValues(contractBets, (bets, contractId) => {
|
||||
const contractsMetrics = mapValues(contractBets, (bets, contractId) => {
|
||||
const contract = contractsById[contractId]
|
||||
if (!contract) return getContractBetNullMetrics()
|
||||
return getContractBetMetrics(contract, bets)
|
||||
|
@ -110,7 +118,7 @@ export function BetsList(props: { user: User }) {
|
|||
(filter === 'open' ? -1 : 1) *
|
||||
(c.resolutionTime ?? c.closeTime ?? Infinity),
|
||||
}
|
||||
const displayedContracts = _.sortBy(contracts, SORTS[sort])
|
||||
const displayedContracts = sortBy(contracts, SORTS[sort])
|
||||
.reverse()
|
||||
.filter(FILTERS[filter])
|
||||
.filter((c) => {
|
||||
|
@ -121,20 +129,20 @@ export function BetsList(props: { user: User }) {
|
|||
return metrics.payout > 0
|
||||
})
|
||||
|
||||
const [settled, unsettled] = _.partition(
|
||||
const [settled, unsettled] = partition(
|
||||
contracts,
|
||||
(c) => c.isResolved || contractsMetrics[c.id].invested === 0
|
||||
)
|
||||
|
||||
const currentInvested = _.sumBy(
|
||||
const currentInvested = sumBy(
|
||||
unsettled,
|
||||
(c) => contractsMetrics[c.id].invested
|
||||
)
|
||||
const currentBetsValue = _.sumBy(
|
||||
const currentBetsValue = sumBy(
|
||||
unsettled,
|
||||
(c) => contractsMetrics[c.id].payout
|
||||
)
|
||||
const currentNetInvestment = _.sumBy(
|
||||
const currentNetInvestment = sumBy(
|
||||
unsettled,
|
||||
(c) => contractsMetrics[c.id].netPayout
|
||||
)
|
||||
|
@ -340,10 +348,10 @@ export function MyBetsSummary(props: {
|
|||
const excludeSalesAndAntes = bets.filter(
|
||||
(b) => !b.isAnte && !b.isSold && !b.sale
|
||||
)
|
||||
const yesWinnings = _.sumBy(excludeSalesAndAntes, (bet) =>
|
||||
const yesWinnings = sumBy(excludeSalesAndAntes, (bet) =>
|
||||
calculatePayout(contract, bet, 'YES')
|
||||
)
|
||||
const noWinnings = _.sumBy(excludeSalesAndAntes, (bet) =>
|
||||
const noWinnings = sumBy(excludeSalesAndAntes, (bet) =>
|
||||
calculatePayout(contract, bet, 'NO')
|
||||
)
|
||||
const { invested, profitPercent, payout, profit } = getContractBetMetrics(
|
||||
|
@ -421,21 +429,19 @@ export function ContractBetsTable(props: {
|
|||
|
||||
const bets = props.bets.filter((b) => !b.isAnte)
|
||||
|
||||
const [sales, buys] = _.partition(bets, (bet) => bet.sale)
|
||||
const [sales, buys] = partition(bets, (bet) => bet.sale)
|
||||
|
||||
const salesDict = _.fromPairs(
|
||||
const salesDict = Object.fromEntries(
|
||||
sales.map((sale) => [sale.sale?.betId ?? '', sale])
|
||||
)
|
||||
|
||||
const [redemptions, normalBets] = _.partition(
|
||||
const [redemptions, normalBets] = partition(
|
||||
contract.mechanism === 'cpmm-1' ? bets : buys,
|
||||
(b) => b.isRedemption
|
||||
)
|
||||
const amountRedeemed = Math.floor(
|
||||
-0.5 * _.sumBy(redemptions, (b) => b.shares)
|
||||
)
|
||||
const amountRedeemed = Math.floor(-0.5 * sumBy(redemptions, (b) => b.shares))
|
||||
|
||||
const amountLoaned = _.sumBy(
|
||||
const amountLoaned = sumBy(
|
||||
bets.filter((bet) => !bet.isSold && !bet.sale),
|
||||
(bet) => bet.loanAmount ?? 0
|
||||
)
|
||||
|
@ -570,10 +576,7 @@ function BetRow(props: { bet: Bet; contract: Contract; saleBet?: Bet }) {
|
|||
)
|
||||
}
|
||||
|
||||
const warmUpSellBet = _.throttle(
|
||||
() => sellBet({}).catch(() => {}),
|
||||
5000 /* ms */
|
||||
)
|
||||
const warmUpSellBet = throttle(() => sellBet({}).catch(() => {}), 5000 /* ms */)
|
||||
|
||||
function SellButton(props: { contract: Contract; bet: Bet }) {
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import _ from 'lodash'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { NumericContract } from 'common/contract'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { StarIcon } from '@heroicons/react/solid'
|
||||
import _ from 'lodash'
|
||||
import { sumBy } from 'lodash'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import { Charity } from 'common/charity'
|
||||
|
@ -11,7 +11,7 @@ export function CharityCard(props: { charity: Charity }) {
|
|||
const { name, slug, photo, preview, id, tags } = props.charity
|
||||
|
||||
const txns = useCharityTxns(id)
|
||||
const raised = _.sumBy(txns, (txn) => txn.amount)
|
||||
const raised = sumBy(txns, (txn) => txn.amount)
|
||||
|
||||
return (
|
||||
<Link href={`/charity/${slug}`} passHref>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DotsHorizontalIcon } from '@heroicons/react/outline'
|
||||
import clsx from 'clsx'
|
||||
import dayjs from 'dayjs'
|
||||
import _ from 'lodash'
|
||||
import { uniqBy, sum } from 'lodash'
|
||||
import { useState } from 'react'
|
||||
import { Bet } from 'common/bet'
|
||||
|
||||
|
@ -26,7 +26,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 tradersCount = _.uniqBy(bets, 'userId').length
|
||||
const tradersCount = uniqBy(bets, 'userId').length
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -108,7 +108,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
|
|||
{contract.mechanism === 'dpm-2' && (
|
||||
<tr>
|
||||
<td>Pool</td>
|
||||
<td>{formatMoney(_.sum(Object.values(contract.pool)))}</td>
|
||||
<td>{formatMoney(sum(Object.values(contract.pool)))}</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { DatumValue } from '@nivo/core'
|
||||
import { ResponsiveLine } from '@nivo/line'
|
||||
import { NUMERIC_GRAPH_COLOR } from 'common/numeric-constants'
|
||||
import _ from 'lodash'
|
||||
import { memo } from 'react'
|
||||
import { range } from 'lodash'
|
||||
import { getDpmOutcomeProbabilities } from '../../../common/calculate-dpm'
|
||||
import { NumericContract } from '../../../common/contract'
|
||||
import { useWindowSize } from '../../hooks/use-window-size'
|
||||
|
@ -16,10 +16,10 @@ export const NumericGraph = memo(function NumericGraph(props: {
|
|||
|
||||
const bucketProbs = getDpmOutcomeProbabilities(totalShares)
|
||||
|
||||
const xs = _.range(bucketCount).map(
|
||||
const xs = range(bucketCount).map(
|
||||
(i) => min + ((max - min) * i) / bucketCount
|
||||
)
|
||||
const probs = _.range(bucketCount).map((i) => bucketProbs[`${i}`] * 100)
|
||||
const probs = range(bucketCount).map((i) => bucketProbs[`${i}`] * 100)
|
||||
const points = probs.map((prob, i) => ({ x: xs[i], y: prob }))
|
||||
const maxProb = Math.max(...probs)
|
||||
const data = [{ id: 'Probability', data: points, color: NUMERIC_GRAPH_COLOR }]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { sample } from 'lodash'
|
||||
import { SparklesIcon, XIcon } from '@heroicons/react/solid'
|
||||
import { Avatar } from './avatar'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
@ -86,9 +86,7 @@ export default function FeedCreate(props: {
|
|||
// Take care not to produce a different placeholder on the server and client
|
||||
const [defaultPlaceholder, setDefaultPlaceholder] = useState('')
|
||||
useEffect(() => {
|
||||
setDefaultPlaceholder(
|
||||
`e.g. ${_.sample(ENV_CONFIG.newQuestionPlaceholders)}`
|
||||
)
|
||||
setDefaultPlaceholder(`e.g. ${sample(ENV_CONFIG.newQuestionPlaceholders)}`)
|
||||
}, [])
|
||||
|
||||
const placeholder = props.placeholder ?? defaultPlaceholder
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { last, findLastIndex, uniq, sortBy } from 'lodash'
|
||||
|
||||
import { Answer } from 'common/answer'
|
||||
import { Bet } from 'common/bet'
|
||||
|
@ -200,17 +200,17 @@ function getAnswerGroups(
|
|||
) {
|
||||
const { sortByProb, abbreviated, reversed } = options
|
||||
|
||||
let outcomes = _.uniq(bets.map((bet) => bet.outcome)).filter(
|
||||
let outcomes = uniq(bets.map((bet) => bet.outcome)).filter(
|
||||
(outcome) => getOutcomeProbability(contract, outcome) > 0.0001
|
||||
)
|
||||
if (abbreviated) {
|
||||
const lastComment = _.last(comments)
|
||||
const lastComment = last(comments)
|
||||
const lastCommentOutcome = bets.find(
|
||||
(bet) => bet.id === lastComment?.betId
|
||||
)?.outcome
|
||||
const lastBetOutcome = _.last(bets)?.outcome
|
||||
const lastBetOutcome = last(bets)?.outcome
|
||||
if (lastCommentOutcome && lastBetOutcome) {
|
||||
outcomes = _.uniq([
|
||||
outcomes = uniq([
|
||||
...outcomes.filter(
|
||||
(outcome) =>
|
||||
outcome !== lastCommentOutcome && outcome !== lastBetOutcome
|
||||
|
@ -222,13 +222,13 @@ function getAnswerGroups(
|
|||
outcomes = outcomes.slice(-2)
|
||||
}
|
||||
if (sortByProb) {
|
||||
outcomes = _.sortBy(outcomes, (outcome) =>
|
||||
outcomes = sortBy(outcomes, (outcome) =>
|
||||
getOutcomeProbability(contract, outcome)
|
||||
)
|
||||
} else {
|
||||
// Sort by recent bet.
|
||||
outcomes = _.sortBy(outcomes, (outcome) =>
|
||||
_.findLastIndex(bets, (bet) => bet.outcome === outcome)
|
||||
outcomes = sortBy(outcomes, (outcome) =>
|
||||
findLastIndex(bets, (bet) => bet.outcome === outcome)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -274,10 +274,10 @@ function getAnswerAndCommentInputGroups(
|
|||
comments: Comment[],
|
||||
user: User | undefined | null
|
||||
) {
|
||||
let outcomes = _.uniq(bets.map((bet) => bet.outcome)).filter(
|
||||
let outcomes = uniq(bets.map((bet) => bet.outcome)).filter(
|
||||
(outcome) => getOutcomeProbability(contract, outcome) > 0.0001
|
||||
)
|
||||
outcomes = _.sortBy(outcomes, (outcome) =>
|
||||
outcomes = sortBy(outcomes, (outcome) =>
|
||||
getOutcomeProbability(contract, outcome)
|
||||
)
|
||||
const betsByCurrentUser = bets.filter((bet) => bet.userId === user?.id)
|
||||
|
@ -343,7 +343,7 @@ function groupBetsAndComments(
|
|||
|
||||
// iterate through the bets and comment activity items and add them to the items in order of comment creation time:
|
||||
const unorderedBetsAndComments = [...commentsWithoutBets, ...groupedBets]
|
||||
let sortedBetsAndComments = _.sortBy(unorderedBetsAndComments, (item) => {
|
||||
let sortedBetsAndComments = sortBy(unorderedBetsAndComments, (item) => {
|
||||
if (item.type === 'comment') {
|
||||
return item.comment.createdTime
|
||||
} else if (item.type === 'bet') {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { formatMoney } from 'common/util/format'
|
|||
import { OutcomeLabel } from 'web/components/outcome-label'
|
||||
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
||||
import React, { Fragment } from 'react'
|
||||
import * as _ from 'lodash'
|
||||
import { uniqBy, partition, sumBy, groupBy } from 'lodash'
|
||||
import { JoinSpans } from 'web/components/join-spans'
|
||||
|
||||
export function FeedBet(props: {
|
||||
|
@ -104,11 +104,11 @@ function BetGroupSpan(props: {
|
|||
}) {
|
||||
const { contract, bets, outcome } = props
|
||||
|
||||
const numberTraders = _.uniqBy(bets, (b) => b.userId).length
|
||||
const numberTraders = uniqBy(bets, (b) => b.userId).length
|
||||
|
||||
const [buys, sells] = _.partition(bets, (bet) => bet.amount >= 0)
|
||||
const buyTotal = _.sumBy(buys, (b) => b.amount)
|
||||
const sellTotal = _.sumBy(sells, (b) => -b.amount)
|
||||
const [buys, sells] = partition(bets, (bet) => bet.amount >= 0)
|
||||
const buyTotal = sumBy(buys, (b) => b.amount)
|
||||
const sellTotal = sumBy(sells, (b) => -b.amount)
|
||||
|
||||
return (
|
||||
<span>
|
||||
|
@ -139,7 +139,7 @@ export function FeedBetGroup(props: {
|
|||
}) {
|
||||
const { contract, bets, hideOutcome } = props
|
||||
|
||||
const betGroups = _.groupBy(bets, (bet) => bet.outcome)
|
||||
const betGroups = groupBy(bets, (bet) => bet.outcome)
|
||||
const outcomes = Object.keys(betGroups)
|
||||
|
||||
// Use the time of the last bet for the entire group
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Comment } from 'common/comment'
|
|||
import { User } from 'common/user'
|
||||
import { Contract } from 'common/contract'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { minBy, maxBy, groupBy, partition, sumBy } from 'lodash'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -16,7 +17,6 @@ import { contractPath } from 'web/lib/firebase/contracts'
|
|||
import { firebaseLogin } from 'web/lib/firebase/users'
|
||||
import { createComment, MAX_COMMENT_LENGTH } from 'web/lib/firebase/comments'
|
||||
import Textarea from 'react-expanding-textarea'
|
||||
import * as _ from 'lodash'
|
||||
import { Linkify } from 'web/components/linkify'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import { BetStatusText } from 'web/components/feed/feed-bets'
|
||||
|
@ -36,7 +36,7 @@ export function FeedCommentThread(props: {
|
|||
props
|
||||
const [showReply, setShowReply] = useState(false)
|
||||
const [replyToUsername, setReplyToUsername] = useState('')
|
||||
const betsByUserId = _.groupBy(bets, (bet) => bet.userId)
|
||||
const betsByUserId = groupBy(bets, (bet) => bet.userId)
|
||||
const user = useUser()
|
||||
const commentsList = comments.filter(
|
||||
(comment) =>
|
||||
|
@ -67,7 +67,7 @@ export function FeedCommentThread(props: {
|
|||
onReplyClick={scrollAndOpenReplyInput}
|
||||
probAtCreatedTime={
|
||||
contract.outcomeType === 'BINARY'
|
||||
? _.minBy(bets, (bet) => {
|
||||
? minBy(bets, (bet) => {
|
||||
return bet.createdTime < comment.createdTime
|
||||
? comment.createdTime - bet.createdTime
|
||||
: comment.createdTime
|
||||
|
@ -494,8 +494,7 @@ function getBettorsLargestPositionBeforeTime(
|
|||
}
|
||||
}
|
||||
const majorityAnswer =
|
||||
_.maxBy(Object.keys(answerCounts), (outcome) => answerCounts[outcome]) ??
|
||||
''
|
||||
maxBy(Object.keys(answerCounts), (outcome) => answerCounts[outcome]) ?? ''
|
||||
return {
|
||||
userPosition: answerCounts[majorityAnswer] || 0,
|
||||
outcome: majorityAnswer,
|
||||
|
@ -505,12 +504,12 @@ function getBettorsLargestPositionBeforeTime(
|
|||
return emptyReturn
|
||||
}
|
||||
|
||||
const [yesBets, noBets] = _.partition(
|
||||
const [yesBets, noBets] = partition(
|
||||
previousBets ?? [],
|
||||
(bet) => bet.outcome === 'YES'
|
||||
)
|
||||
yesShares = _.sumBy(yesBets, (bet) => bet.shares)
|
||||
noShares = _.sumBy(noBets, (bet) => bet.shares)
|
||||
yesShares = sumBy(yesBets, (bet) => bet.shares)
|
||||
noShares = sumBy(noBets, (bet) => bet.shares)
|
||||
yesFloorShares = Math.floor(yesShares)
|
||||
noFloorShares = Math.floor(noShares)
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// From https://tailwindui.com/components/application-ui/lists/feeds
|
||||
import React, { useState } from 'react'
|
||||
import * as _ from 'lodash'
|
||||
import {
|
||||
BanIcon,
|
||||
CheckIcon,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { groupBy, mapValues, maxBy, sortBy } from 'lodash'
|
||||
import { Contract } from 'web/lib/firebase/contracts'
|
||||
import { Comment } from 'web/lib/firebase/comments'
|
||||
import { Bet } from 'common/bet'
|
||||
|
@ -44,10 +44,10 @@ export function findActiveContracts(
|
|||
}
|
||||
|
||||
// Add contracts by last bet time.
|
||||
const contractBets = _.groupBy(recentBets, (bet) => bet.contractId)
|
||||
const contractMostRecentBet = _.mapValues(
|
||||
const contractBets = groupBy(recentBets, (bet) => bet.contractId)
|
||||
const contractMostRecentBet = mapValues(
|
||||
contractBets,
|
||||
(bets) => _.maxBy(bets, (bet) => bet.createdTime) as Bet
|
||||
(bets) => maxBy(bets, (bet) => bet.createdTime) as Bet
|
||||
)
|
||||
for (const bet of Object.values(contractMostRecentBet)) {
|
||||
const contract = contractsById.get(bet.contractId)
|
||||
|
@ -60,21 +60,21 @@ export function findActiveContracts(
|
|||
!contract.isResolved &&
|
||||
(contract.closeTime ?? Infinity) > Date.now()
|
||||
)
|
||||
activeContracts = _.sortBy(
|
||||
activeContracts = sortBy(
|
||||
activeContracts,
|
||||
(c) => -(idToActivityTime.get(c.id) ?? 0)
|
||||
)
|
||||
|
||||
const contractComments = _.groupBy(
|
||||
const contractComments = groupBy(
|
||||
recentComments,
|
||||
(comment) => comment.contractId
|
||||
)
|
||||
const contractMostRecentComment = _.mapValues(
|
||||
const contractMostRecentComment = mapValues(
|
||||
contractComments,
|
||||
(comments) => _.maxBy(comments, (c) => c.createdTime) as Comment
|
||||
(comments) => maxBy(comments, (c) => c.createdTime) as Comment
|
||||
)
|
||||
|
||||
const prioritizedContracts = _.sortBy(activeContracts, (c) => {
|
||||
const prioritizedContracts = sortBy(activeContracts, (c) => {
|
||||
const seenTime = seenContracts[c.id]
|
||||
if (!seenTime) {
|
||||
return 0
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useState } from 'react'
|
||||
import _ from 'lodash'
|
||||
import { isEqual } from 'lodash'
|
||||
import clsx from 'clsx'
|
||||
import { PencilIcon } from '@heroicons/react/outline'
|
||||
|
||||
|
@ -29,7 +29,7 @@ export function EditFoldButton(props: { fold: Fold; className?: string }) {
|
|||
|
||||
const saveDisabled =
|
||||
name === fold.name &&
|
||||
_.isEqual(tags, fold.tags) &&
|
||||
isEqual(tags, fold.tags) &&
|
||||
about === (fold.about ?? '')
|
||||
|
||||
const onSubmit = async () => {
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
SparklesIcon,
|
||||
} from '@heroicons/react/outline'
|
||||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useFollowedFolds } from 'web/hooks/use-fold'
|
||||
|
@ -124,7 +124,7 @@ export default function Sidebar(props: { className?: string }) {
|
|||
|
||||
const user = useUser()
|
||||
let folds = useFollowedFolds(user) || []
|
||||
folds = _.sortBy(folds, 'followCount').reverse()
|
||||
folds = sortBy(folds, 'followCount').reverse()
|
||||
const deservesDailyFreeMarket = !useHasCreatedContractToday(user)
|
||||
|
||||
const navigationOptions =
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
|
||||
import { Col } from './layout/col'
|
||||
import { Spacer } from './layout/spacer'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Binary, CPMM, DPM, FullContract } from 'common/contract'
|
||||
import { Bet } from 'common/bet'
|
||||
import { useEffect, useState } from 'react'
|
||||
import _ from 'lodash'
|
||||
import { partition, sumBy } from 'lodash'
|
||||
|
||||
export const useSaveShares = (
|
||||
contract: FullContract<CPMM | DPM, Binary>,
|
||||
|
@ -17,13 +17,13 @@ export const useSaveShares = (
|
|||
| undefined
|
||||
>()
|
||||
|
||||
const [yesBets, noBets] = _.partition(
|
||||
const [yesBets, noBets] = partition(
|
||||
userBets ?? [],
|
||||
(bet) => bet.outcome === 'YES'
|
||||
)
|
||||
const [yesShares, noShares] = [
|
||||
_.sumBy(yesBets, (bet) => bet.shares),
|
||||
_.sumBy(noBets, (bet) => bet.shares),
|
||||
sumBy(yesBets, (bet) => bet.shares),
|
||||
sumBy(noBets, (bet) => bet.shares),
|
||||
]
|
||||
|
||||
const yesFloorShares = Math.round(yesShares) === 0 ? 0 : Math.floor(yesShares)
|
||||
|
|
|
@ -19,10 +19,10 @@ import { Comment, getUsersComments } from 'web/lib/firebase/comments'
|
|||
import { Contract } from 'common/contract'
|
||||
import { getContractFromId, listContracts } from 'web/lib/firebase/contracts'
|
||||
import { LoadingIndicator } from './loading-indicator'
|
||||
import _ from 'lodash'
|
||||
import { BetsList } from './bets-list'
|
||||
import { Bet } from 'common/bet'
|
||||
import { getUserBets } from 'web/lib/firebase/bets'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
export function UserLink(props: {
|
||||
name: string
|
||||
|
@ -70,7 +70,7 @@ export function UserPage(props: {
|
|||
}, [user])
|
||||
|
||||
useEffect(() => {
|
||||
const uniqueContractIds = _.uniq(
|
||||
const uniqueContractIds = uniq(
|
||||
usersComments.map((comment) => comment.contractId)
|
||||
)
|
||||
Promise.all(
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import _, { Dictionary } from 'lodash'
|
||||
import { useState, useEffect } from 'react'
|
||||
import type { feed } from 'common/feed'
|
||||
import { useTimeSinceFirstRender } from './use-time-since-first-render'
|
||||
|
@ -15,7 +14,7 @@ export const useAlgoFeed = (
|
|||
category: string
|
||||
) => {
|
||||
const [allFeed, setAllFeed] = useState<feed>()
|
||||
const [categoryFeeds, setCategoryFeeds] = useState<Dictionary<feed>>()
|
||||
const [categoryFeeds, setCategoryFeeds] = useState<{ [x: string]: feed }>()
|
||||
|
||||
const getTime = useTimeSinceFirstRender()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { isEqual } from 'lodash'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
Contract,
|
||||
|
@ -80,14 +80,14 @@ export const useUpdatedContracts = (contracts: Contract[] | undefined) => {
|
|||
useEffect(() => {
|
||||
if (contracts === undefined) return
|
||||
|
||||
contractDict.current = _.fromPairs(contracts.map((c) => [c.id, c]))
|
||||
contractDict.current = Object.fromEntries(contracts.map((c) => [c.id, c]))
|
||||
|
||||
const disposes = contracts.map((contract) => {
|
||||
const { id } = contract
|
||||
|
||||
return listenForContract(id, (contract) => {
|
||||
const curr = contractDict.current[id]
|
||||
if (!_.isEqual(curr, contract)) {
|
||||
if (!isEqual(curr, contract)) {
|
||||
contractDict.current[id] = contract as Contract
|
||||
triggerUpdate((n) => n + 1)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { isEqual, sortBy } from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Fold } from 'common/fold'
|
||||
import { User } from 'common/user'
|
||||
|
@ -95,9 +95,9 @@ export const useFollowedFolds = (user: User | null | undefined) => {
|
|||
setFollowedFolds(JSON.parse(followedFoldJson))
|
||||
// Exit early if ids and followedFoldIds have all the same elements.
|
||||
if (
|
||||
_.isEqual(
|
||||
_.sortBy(ids),
|
||||
_.sortBy(JSON.parse(followedFoldJson).map((f: Fold) => f.id))
|
||||
isEqual(
|
||||
sortBy(ids),
|
||||
sortBy(JSON.parse(followedFoldJson).map((f: Fold) => f.id))
|
||||
)
|
||||
) {
|
||||
return
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { debounce } from 'lodash'
|
||||
import { RefObject, useMemo, useLayoutEffect, useRef, useState } from 'react'
|
||||
|
||||
type elem_size =
|
||||
|
@ -21,7 +21,7 @@ export function useListenElemSize<T extends HTMLElement>(
|
|||
}
|
||||
|
||||
return debounceMs
|
||||
? _.debounce(updateSize, debounceMs, { leading: false, trailing: true })
|
||||
? debounce(updateSize, debounceMs, { leading: false, trailing: true })
|
||||
: updateSize
|
||||
}, [callback, elemRef, debounceMs])
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
||||
|
@ -16,7 +16,7 @@ export function usePropz(
|
|||
getStaticPropz: (props: PropzProps) => Promise<any>
|
||||
) {
|
||||
// If props were successfully server-side generated, just use those
|
||||
if (!_.isEmpty(initialProps)) {
|
||||
if (!isEmpty(initialProps)) {
|
||||
return initialProps
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { mapValues } from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Contract } from 'common/contract'
|
||||
import { trackView } from 'web/lib/firebase/tracking'
|
||||
|
@ -38,7 +38,7 @@ export const useSaveSeenContract = (
|
|||
const key = 'feed-seen-contracts'
|
||||
|
||||
const getSeenContracts = () => {
|
||||
return _.mapValues(
|
||||
return mapValues(
|
||||
JSON.parse(localStorage.getItem(key) ?? '{}'),
|
||||
(time) => +time
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { defaults, debounce } from 'lodash'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useSearchBox } from 'react-instantsearch-hooks-web'
|
||||
|
@ -18,7 +18,7 @@ export function useInitialQueryAndSort(options?: {
|
|||
defaultSort: Sort
|
||||
shouldLoadFromStorage?: boolean
|
||||
}) {
|
||||
const { defaultSort, shouldLoadFromStorage } = _.defaults(options, {
|
||||
const { defaultSort, shouldLoadFromStorage } = defaults(options, {
|
||||
defaultSort: '24-hour-vol',
|
||||
shouldLoadFromStorage: true,
|
||||
})
|
||||
|
@ -79,7 +79,7 @@ export function useUpdateQueryAndSort(props: {
|
|||
// Debounce router query update.
|
||||
const pushQuery = useMemo(
|
||||
() =>
|
||||
_.debounce((query: string | undefined) => {
|
||||
debounce((query: string | undefined) => {
|
||||
if (query) {
|
||||
router.query.q = query
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { isEqual } from 'lodash'
|
||||
import { useMemo, useRef, useState } from 'react'
|
||||
|
||||
export const useStateCheckEquality = <T>(initialState: T) => {
|
||||
|
@ -10,7 +10,7 @@ export const useStateCheckEquality = <T>(initialState: T) => {
|
|||
const checkSetState = useMemo(
|
||||
() => (newState: T) => {
|
||||
const state = stateRef.current
|
||||
if (!_.isEqual(state, newState)) {
|
||||
if (!isEqual(state, newState)) {
|
||||
setState(newState)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { uniq } from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
import {
|
||||
Bet,
|
||||
|
@ -51,7 +51,7 @@ export const useUserBetContracts = (
|
|||
return listenForUserBets(
|
||||
userId,
|
||||
(bets) => {
|
||||
const contractIds = _.uniq(bets.map((bet) => bet.contractId))
|
||||
const contractIds = uniq(bets.map((bet) => bet.contractId))
|
||||
setContractIds(contractIds)
|
||||
localStorage.setItem(key, JSON.stringify(contractIds))
|
||||
},
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import _ from 'lodash'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { PrivateUser } from 'common/user'
|
||||
import {
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
where,
|
||||
orderBy,
|
||||
} from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
import { range } from 'lodash'
|
||||
|
||||
import { db } from './init'
|
||||
import { Bet } from 'common/bet'
|
||||
|
@ -138,7 +138,7 @@ export async function getDailyBets(startTime: number, numberOfDays: number) {
|
|||
const query = getBetsQuery(startTime, startTime + DAY_IN_MS * numberOfDays)
|
||||
const bets = await getValues<Bet>(query)
|
||||
|
||||
const betsByDay = _.range(0, numberOfDays).map(() => [] as Bet[])
|
||||
const betsByDay = range(0, numberOfDays).map(() => [] as Bet[])
|
||||
for (const bet of bets) {
|
||||
const dayIndex = Math.floor((bet.createdTime - startTime) / DAY_IN_MS)
|
||||
betsByDay[dayIndex].push(bet)
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
setDoc,
|
||||
where,
|
||||
} from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
import { range } from 'lodash'
|
||||
|
||||
import { getValues, listenForValues } from './utils'
|
||||
import { db } from './init'
|
||||
|
@ -117,7 +117,7 @@ export async function getDailyComments(
|
|||
)
|
||||
const comments = await getValues<Comment>(query)
|
||||
|
||||
const commentsByDay = _.range(0, numberOfDays).map(() => [] as Comment[])
|
||||
const commentsByDay = range(0, numberOfDays).map(() => [] as Comment[])
|
||||
for (const comment of comments) {
|
||||
const dayIndex = Math.floor((comment.createdTime - startTime) / DAY_IN_MS)
|
||||
commentsByDay[dayIndex].push(comment)
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
updateDoc,
|
||||
limit,
|
||||
} from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
import { range, sortBy } from 'lodash'
|
||||
|
||||
import { app } from './init'
|
||||
import { getValues, listenForValue, listenForValues } from './utils'
|
||||
|
@ -225,7 +225,7 @@ export function listenForHotContracts(
|
|||
setHotContracts: (contracts: Contract[]) => void
|
||||
) {
|
||||
return listenForValues<Contract>(hotContractsQuery, (contracts) => {
|
||||
const hotContracts = _.sortBy(
|
||||
const hotContracts = sortBy(
|
||||
chooseRandomSubset(contracts, 4),
|
||||
(contract) => contract.volume24Hours
|
||||
)
|
||||
|
@ -235,7 +235,7 @@ export function listenForHotContracts(
|
|||
|
||||
export async function getHotContracts() {
|
||||
const contracts = await getValues<Contract>(hotContractsQuery)
|
||||
return _.sortBy(
|
||||
return sortBy(
|
||||
chooseRandomSubset(contracts, 10),
|
||||
(contract) => -1 * contract.volume24Hours
|
||||
)
|
||||
|
@ -245,7 +245,7 @@ export async function getContractsBySlugs(slugs: string[]) {
|
|||
const q = query(contractCollection, where('slug', 'in', slugs))
|
||||
const snapshot = await getDocs(q)
|
||||
const contracts = snapshot.docs.map((doc) => doc.data() as Contract)
|
||||
return _.sortBy(contracts, (contract) => -1 * contract.volume24Hours)
|
||||
return sortBy(contracts, (contract) => -1 * contract.volume24Hours)
|
||||
}
|
||||
|
||||
const topWeeklyQuery = query(
|
||||
|
@ -269,7 +269,7 @@ const closingSoonQuery = query(
|
|||
|
||||
export async function getClosingSoonContracts() {
|
||||
const contracts = await getValues<Contract>(closingSoonQuery)
|
||||
return _.sortBy(
|
||||
return sortBy(
|
||||
chooseRandomSubset(contracts, 2),
|
||||
(contract) => contract.closeTime
|
||||
)
|
||||
|
@ -295,7 +295,7 @@ export async function getDailyContracts(
|
|||
)
|
||||
const contracts = await getValues<Contract>(query)
|
||||
|
||||
const contractsByDay = _.range(0, numberOfDays).map(() => [] as Contract[])
|
||||
const contractsByDay = range(0, numberOfDays).map(() => [] as Contract[])
|
||||
for (const contract of contracts) {
|
||||
const dayIndex = Math.floor((contract.createdTime - startTime) / DAY_IN_MS)
|
||||
contractsByDay[dayIndex].push(contract)
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
updateDoc,
|
||||
where,
|
||||
} from 'firebase/firestore'
|
||||
import _ from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
import { Fold } from 'common/fold'
|
||||
import { Contract, contractCollection } from './contracts'
|
||||
import { db } from './init'
|
||||
|
@ -171,7 +171,7 @@ export async function getFoldsByTags(tags: string[]) {
|
|||
)
|
||||
)
|
||||
|
||||
return _.sortBy(folds, (fold) => -1 * fold.followCount)
|
||||
return sortBy(folds, (fold) => -1 * fold.followCount)
|
||||
}
|
||||
|
||||
export function listenForFoldsWithTags(
|
||||
|
@ -187,7 +187,7 @@ export function listenForFoldsWithTags(
|
|||
)
|
||||
|
||||
return listenForValues<Fold>(q, (folds) => {
|
||||
const sorted = _.sortBy(folds, (fold) => -1 * fold.followCount)
|
||||
const sorted = sortBy(folds, (fold) => -1 * fold.followCount)
|
||||
setFolds(sorted)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
GoogleAuthProvider,
|
||||
signInWithPopup,
|
||||
} from 'firebase/auth'
|
||||
import _ from 'lodash'
|
||||
import { range, throttle, zip } from 'lodash'
|
||||
|
||||
import { app } from './init'
|
||||
import { PrivateUser, User } from 'common/user'
|
||||
|
@ -83,7 +83,7 @@ const CACHED_USER_KEY = 'CACHED_USER_KEY'
|
|||
// used to avoid weird race condition
|
||||
let createUserPromise: Promise<User | null> | undefined = undefined
|
||||
|
||||
const warmUpCreateUser = _.throttle(createUser, 5000 /* ms */)
|
||||
const warmUpCreateUser = throttle(createUser, 5000 /* ms */)
|
||||
|
||||
export function listenForLogin(onUser: (user: User | null) => void) {
|
||||
const cachedUser = localStorage.getItem(CACHED_USER_KEY)
|
||||
|
@ -210,7 +210,7 @@ export async function getDailyNewUsers(
|
|||
const query = getUsersQuery(startTime, startTime + DAY_MS * numberOfDays)
|
||||
const users = await getValues<User>(query)
|
||||
|
||||
const usersByDay = _.range(0, numberOfDays).map(() => [] as User[])
|
||||
const usersByDay = range(0, numberOfDays).map(() => [] as User[])
|
||||
for (const user of users) {
|
||||
const dayIndex = Math.floor((user.createdTime - startTime) / DAY_MS)
|
||||
usersByDay[dayIndex].push(user)
|
||||
|
@ -235,5 +235,5 @@ export async function getCategoryFeeds(userId: string) {
|
|||
)
|
||||
)
|
||||
const feeds = feedData.map((data) => data?.feed ?? [])
|
||||
return _.fromPairs(_.zip(CATEGORY_LIST, feeds) as [string, feed][])
|
||||
return Object.fromEntries(zip(CATEGORY_LIST, feeds) as [string, feed][])
|
||||
}
|
||||
|
|
|
@ -6,6 +6,11 @@ module.exports = {
|
|||
experimental: {
|
||||
externalDir: true,
|
||||
optimizeCss: true,
|
||||
modularizeImports: {
|
||||
lodash: {
|
||||
transform: 'lodash/{{member}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
images: {
|
||||
domains: ['lh3.googleusercontent.com', 'i.imgur.com'],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { ArrowLeftIcon } from '@heroicons/react/outline'
|
||||
import _ from 'lodash'
|
||||
import { keyBy, sortBy, groupBy, sumBy, mapValues } from 'lodash'
|
||||
|
||||
import { useContractWithPreload } from 'web/hooks/use-contract'
|
||||
import { ContractOverview } from 'web/components/contract/contract-overview'
|
||||
|
@ -250,13 +250,13 @@ function ContractLeaderboard(props: { contract: Contract; bets: Bet[] }) {
|
|||
|
||||
const { userProfits, top5Ids } = useMemo(() => {
|
||||
// Create a map of userIds to total profits (including sales)
|
||||
const betsByUser = _.groupBy(bets, 'userId')
|
||||
const userProfits = _.mapValues(betsByUser, (bets) =>
|
||||
_.sumBy(bets, (bet) => resolvedPayout(contract, bet) - bet.amount)
|
||||
const betsByUser = groupBy(bets, 'userId')
|
||||
const userProfits = mapValues(betsByUser, (bets) =>
|
||||
sumBy(bets, (bet) => resolvedPayout(contract, bet) - bet.amount)
|
||||
)
|
||||
// Find the 5 users with the most profits
|
||||
const top5Ids = _.entries(userProfits)
|
||||
.sort(([i1, p1], [i2, p2]) => p2 - p1)
|
||||
const top5Ids = Object.entries(userProfits)
|
||||
.sort(([_i1, p1], [_i2, p2]) => p2 - p1)
|
||||
.filter(([, p]) => p > 0)
|
||||
.slice(0, 5)
|
||||
.map(([id]) => id)
|
||||
|
@ -267,7 +267,7 @@ function ContractLeaderboard(props: { contract: Contract; bets: Bet[] }) {
|
|||
console.log('foo')
|
||||
if (top5Ids.length > 0) {
|
||||
listUsers(top5Ids).then((users) => {
|
||||
const sortedUsers = _.sortBy(users, (user) => -userProfits[user.id])
|
||||
const sortedUsers = sortBy(users, (user) => -userProfits[user.id])
|
||||
setUsers(sortedUsers)
|
||||
})
|
||||
}
|
||||
|
@ -294,8 +294,8 @@ function ContractTopTrades(props: {
|
|||
comments: Comment[]
|
||||
}) {
|
||||
const { contract, bets, comments } = props
|
||||
const commentsById = _.keyBy(comments, 'id')
|
||||
const betsById = _.keyBy(bets, 'id')
|
||||
const commentsById = keyBy(comments, 'id')
|
||||
const betsById = keyBy(bets, 'id')
|
||||
|
||||
// If 'id2' is the sale of 'id1', both are logged with (id2 - id1) of profit
|
||||
// Otherwise, we record the profit at resolution time
|
||||
|
@ -312,11 +312,11 @@ function ContractTopTrades(props: {
|
|||
}
|
||||
|
||||
// Now find the betId with the highest profit
|
||||
const topBetId = _.sortBy(bets, (b) => -profitById[b.id])[0]?.id
|
||||
const topBetId = sortBy(bets, (b) => -profitById[b.id])[0]?.id
|
||||
const topBettor = useUserById(betsById[topBetId]?.userId)
|
||||
|
||||
// And also the commentId of the comment with the highest profit
|
||||
const topCommentId = _.sortBy(
|
||||
const topCommentId = sortBy(
|
||||
comments,
|
||||
(c) => c.betId && -profitById[c.betId]
|
||||
)[0]?.id
|
||||
|
|
|
@ -6,7 +6,7 @@ import dayjs from 'dayjs'
|
|||
import { usePrivateUsers, useUsers } from 'web/hooks/use-users'
|
||||
import Custom404 from './404'
|
||||
import { useContracts } from 'web/hooks/use-contracts'
|
||||
import _ from 'lodash'
|
||||
import { mapKeys } from 'lodash'
|
||||
import { useAdmin } from 'web/hooks/use-admin'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
|
||||
|
@ -23,7 +23,7 @@ function UsersTable() {
|
|||
let privateUsers = usePrivateUsers()
|
||||
|
||||
// Map private users by user id
|
||||
const privateUsersById = _.mapKeys(privateUsers, 'id')
|
||||
const privateUsersById = mapKeys(privateUsers, 'id')
|
||||
console.log('private users by id', privateUsersById)
|
||||
|
||||
// For each user, set their email from the PrivateUser
|
||||
|
@ -64,7 +64,7 @@ function UsersTable() {
|
|||
id: 'username',
|
||||
name: 'Username',
|
||||
formatter: (cell) =>
|
||||
html(`<a
|
||||
html(`<a
|
||||
class="hover:underline hover:decoration-indigo-400 hover:decoration-2"
|
||||
href="/${cell}">@${cell}</a>`),
|
||||
},
|
||||
|
@ -134,7 +134,7 @@ function ContractsTable() {
|
|||
id: 'creatorUsername',
|
||||
name: 'Username',
|
||||
formatter: (cell) =>
|
||||
html(`<a
|
||||
html(`<a
|
||||
class="hover:underline hover:decoration-indigo-400 hover:decoration-2"
|
||||
target="_blank"
|
||||
href="/${cell}">@${cell}</a>`),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import dayjs from 'dayjs'
|
||||
import _ from 'lodash'
|
||||
import { zip, uniq, sumBy } from 'lodash'
|
||||
import { IS_PRIVATE_MANIFOLD } from 'common/envs/constants'
|
||||
import {
|
||||
DailyCountChart,
|
||||
|
@ -40,12 +40,12 @@ export async function getStaticPropz() {
|
|||
)
|
||||
const dailyCommentCounts = dailyComments.map((comments) => comments.length)
|
||||
|
||||
const dailyUserIds = _.zip(dailyContracts, dailyBets, dailyComments).map(
|
||||
const dailyUserIds = zip(dailyContracts, dailyBets, dailyComments).map(
|
||||
([contracts, bets, comments]) => {
|
||||
const creatorIds = (contracts ?? []).map((c) => c.creatorId)
|
||||
const betUserIds = (bets ?? []).map((bet) => bet.userId)
|
||||
const commentUserIds = (comments ?? []).map((comment) => comment.userId)
|
||||
return _.uniq([...creatorIds, ...betUserIds, ...commentUserIds])
|
||||
return uniq([...creatorIds, ...betUserIds, ...commentUserIds])
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -87,7 +87,7 @@ export async function getStaticPropz() {
|
|||
for (let j = lastWeek.start; j <= lastWeek.end; j++) {
|
||||
dailyUserIds[j].forEach((userId) => activeLastWeek.add(userId))
|
||||
}
|
||||
const retainedCount = _.sumBy(Array.from(activeTwoWeeksAgo), (userId) =>
|
||||
const retainedCount = sumBy(Array.from(activeTwoWeeksAgo), (userId) =>
|
||||
activeLastWeek.has(userId) ? 1 : 0
|
||||
)
|
||||
const retainedFrac = retainedCount / activeTwoWeeksAgo.size
|
||||
|
@ -112,7 +112,7 @@ export async function getStaticPropz() {
|
|||
for (let j = lastMonth.start; j <= lastMonth.end; j++) {
|
||||
dailyUserIds[j].forEach((userId) => activeLastMonth.add(userId))
|
||||
}
|
||||
const retainedCount = _.sumBy(Array.from(activeTwoMonthsAgo), (userId) =>
|
||||
const retainedCount = sumBy(Array.from(activeTwoMonthsAgo), (userId) =>
|
||||
activeLastMonth.has(userId) ? 1 : 0
|
||||
)
|
||||
const retainedFrac = retainedCount / activeTwoMonthsAgo.size
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { sortBy, sumBy, uniqBy } from 'lodash'
|
||||
import clsx from 'clsx'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
|
@ -41,13 +41,13 @@ function CharityPage(props: { charity: Charity }) {
|
|||
const user = useUser()
|
||||
|
||||
const txns = useCharityTxns(charity.id)
|
||||
const newToOld = _.sortBy(txns, (txn) => -txn.createdTime)
|
||||
const totalRaised = _.sumBy(txns, (txn) => txn.amount)
|
||||
const fromYou = _.sumBy(
|
||||
const newToOld = sortBy(txns, (txn) => -txn.createdTime)
|
||||
const totalRaised = sumBy(txns, (txn) => txn.amount)
|
||||
const fromYou = sumBy(
|
||||
txns.filter((txn) => txn.fromId === user?.id),
|
||||
(txn) => txn.amount
|
||||
)
|
||||
const numSupporters = _.uniqBy(txns, (txn) => txn.fromId).length
|
||||
const numSupporters = uniqBy(txns, (txn) => txn.fromId).length
|
||||
|
||||
const { width, height } = useWindowSize()
|
||||
const [showConfetti, setShowConfetti] = useState(false)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { mapValues, groupBy, sumBy, sum, sortBy, debounce } from 'lodash'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { charities, Charity as CharityType } from 'common/charity'
|
||||
import { CharityCard } from 'web/components/charity/charity-card'
|
||||
|
@ -12,11 +12,11 @@ import { formatMoney } from 'common/util/format'
|
|||
|
||||
export async function getStaticProps() {
|
||||
const txns = await getAllCharityTxns()
|
||||
const totals = _.mapValues(_.groupBy(txns, 'toId'), (txns) =>
|
||||
_.sumBy(txns, (txn) => txn.amount)
|
||||
const totals = mapValues(groupBy(txns, 'toId'), (txns) =>
|
||||
sumBy(txns, (txn) => txn.amount)
|
||||
)
|
||||
const totalRaised = _.sum(Object.values(totals))
|
||||
const sortedCharities = _.sortBy(charities, [
|
||||
const totalRaised = sum(Object.values(totals))
|
||||
const sortedCharities = sortBy(charities, [
|
||||
(charity) => (charity.tags?.includes('Featured') ? 0 : 1),
|
||||
(charity) => -totals[charity.id],
|
||||
])
|
||||
|
@ -37,7 +37,7 @@ export default function Charity(props: {
|
|||
const { totalRaised, charities } = props
|
||||
|
||||
const [query, setQuery] = useState('')
|
||||
const debouncedQuery = _.debounce(setQuery, 50)
|
||||
const debouncedQuery = debounce(setQuery, 50)
|
||||
|
||||
const filterCharities = useMemo(
|
||||
() =>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { flatten, take, partition, sortBy } from 'lodash'
|
||||
|
||||
import { Fold } from 'common/fold'
|
||||
import { Comment } from 'common/comment'
|
||||
|
@ -47,8 +47,8 @@ export async function getStaticPropz(props: { params: { slugs: string[] } }) {
|
|||
contracts.map((contract) => listAllBets(contract.id))
|
||||
)
|
||||
|
||||
let activeContracts = findActiveContracts(contracts, [], _.flatten(bets), {})
|
||||
const [resolved, unresolved] = _.partition(
|
||||
let activeContracts = findActiveContracts(contracts, [], flatten(bets), {})
|
||||
const [resolved, unresolved] = partition(
|
||||
activeContracts,
|
||||
({ isResolved }) => isResolved
|
||||
)
|
||||
|
@ -80,8 +80,8 @@ export async function getStaticPropz(props: { params: { slugs: string[] } }) {
|
|||
}
|
||||
|
||||
async function toTopUsers(userScores: { [userId: string]: number }) {
|
||||
const topUserPairs = _.take(
|
||||
_.sortBy(Object.entries(userScores), ([_, score]) => -1 * score),
|
||||
const topUserPairs = take(
|
||||
sortBy(Object.entries(userScores), ([_, score]) => -1 * score),
|
||||
10
|
||||
).filter(([_, score]) => score >= 0.5)
|
||||
|
||||
|
@ -134,7 +134,7 @@ export default function FoldPage(props: {
|
|||
const isCurator = user && fold && user.id === fold.curatorId
|
||||
|
||||
const taggedContracts = useTaggedContracts(fold?.tags) ?? props.contracts
|
||||
const contractsMap = _.fromPairs(
|
||||
const contractsMap = Object.fromEntries(
|
||||
taggedContracts.map((contract) => [contract.id, contract])
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { sortBy, debounce } from 'lodash'
|
||||
import Link from 'next/link'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Fold } from 'common/fold'
|
||||
|
@ -21,7 +21,7 @@ export async function getStaticProps() {
|
|||
const curators = await Promise.all(
|
||||
folds.map((fold) => getUser(fold.curatorId))
|
||||
)
|
||||
const curatorsDict = _.fromPairs(
|
||||
const curatorsDict = Object.fromEntries(
|
||||
curators.map((curator) => [curator.id, curator])
|
||||
)
|
||||
|
||||
|
@ -37,7 +37,7 @@ export async function getStaticProps() {
|
|||
|
||||
export default function Folds(props: {
|
||||
folds: Fold[]
|
||||
curatorsDict: _.Dictionary<User>
|
||||
curatorsDict: { [k: string]: User }
|
||||
}) {
|
||||
const [curatorsDict, setCuratorsDict] = useState(props.curatorsDict)
|
||||
|
||||
|
@ -51,7 +51,7 @@ export default function Folds(props: {
|
|||
if (newFolds.length > 0) {
|
||||
Promise.all(newFolds.map(({ curatorId }) => getUser(curatorId))).then(
|
||||
(newUsers) => {
|
||||
const newUsersDict = _.fromPairs(
|
||||
const newUsersDict = Object.fromEntries(
|
||||
newUsers.map((user) => [user.id, user])
|
||||
)
|
||||
setCuratorsDict({ ...curatorsDict, ...newUsersDict })
|
||||
|
@ -68,7 +68,7 @@ export default function Folds(props: {
|
|||
}
|
||||
|
||||
// List followed folds first, then folds with the highest follower count
|
||||
const matches = _.sortBy(folds, [
|
||||
const matches = sortBy(folds, [
|
||||
(fold) => !followedFoldIds.includes(fold.id),
|
||||
(fold) => -1 * fold.followCount,
|
||||
]).filter(
|
||||
|
@ -79,7 +79,7 @@ export default function Folds(props: {
|
|||
check(f.lowercaseTags.map((tag) => `#${tag}`).join(' '))
|
||||
)
|
||||
// Not strictly necessary, but makes the "hold delete" experience less laggy
|
||||
const debouncedQuery = _.debounce(setQuery, 50)
|
||||
const debouncedQuery = debounce(setQuery, 50)
|
||||
|
||||
return (
|
||||
<Page>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import { sortBy } from 'lodash'
|
||||
import { GetServerSideProps } from 'next'
|
||||
import { getServerSideSitemap, ISitemapField } from 'next-sitemap'
|
||||
|
||||
|
@ -10,7 +10,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
|||
const response = await fetch(`https://${DOMAIN}/api/v0/markets`)
|
||||
|
||||
const liteMarkets = (await response.json()) as LiteMarket[]
|
||||
const sortedMarkets = _.sortBy(liteMarkets, (m) => -m.volume24Hours)
|
||||
const sortedMarkets = sortBy(liteMarkets, (m) => -m.volume24Hours)
|
||||
|
||||
const fields = sortedMarkets.map((market) => ({
|
||||
// See https://www.sitemaps.org/protocol.html
|
||||
|
|
|
@ -2394,6 +2394,13 @@ eslint-plugin-jsx-a11y@^6.5.1:
|
|||
language-tags "^1.0.5"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
eslint-plugin-lodash@^7.4.0:
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-lodash/-/eslint-plugin-lodash-7.4.0.tgz#14a761547f126c92ff56789662a20a44f8bb6290"
|
||||
integrity sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==
|
||||
dependencies:
|
||||
lodash "^4.17.21"
|
||||
|
||||
eslint-plugin-react-hooks@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz#5f762dfedf8b2cf431c689f533c9d3fa5dcf25ad"
|
||||
|
|
Loading…
Reference in New Issue
Block a user