make earning more tangible
This commit is contained in:
parent
9581160944
commit
7aa6a02a08
|
@ -1,25 +0,0 @@
|
|||
// https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function
|
||||
// const z = 1.281551565545 // 80% confidence
|
||||
// const z = 1.644853626951 // 90% confidence
|
||||
// const z = 1.959963984540 // 95% confidence
|
||||
const z = 3.090232306168 // 98% confidence
|
||||
|
||||
function confidence (s, n) {
|
||||
if (n === 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const p = s / n
|
||||
const left = p + 1 / (2 * n) * z * z
|
||||
const right = z * Math.sqrt(p * (1 - p) / n + z * z / (4 * n * n))
|
||||
const under = 1 + 1 / n * z * z
|
||||
|
||||
return (left - right) / under
|
||||
}
|
||||
|
||||
console.log(confidence(process.argv[2], process.argv[3]))
|
||||
|
||||
/*
|
||||
Need to describe how they'll earn
|
||||
If we trust upvotes how can we use that to determine the best
|
||||
*/
|
113
worker/earn.js
113
worker/earn.js
|
@ -1,5 +1,10 @@
|
|||
const serialize = require('../api/resolvers/serial')
|
||||
|
||||
const ITEM_EACH_REWARD = 3.0
|
||||
const UPVOTE_EACH_REWARD = 6.0
|
||||
const TOP_ITEMS = 21
|
||||
const EARLY_MULTIPLIER_MAX = 100.0
|
||||
|
||||
// TODO: use a weekly trust measure or make trust decay
|
||||
function earn ({ models }) {
|
||||
return async function ({ name }) {
|
||||
|
@ -14,18 +19,63 @@ function earn ({ models }) {
|
|||
OR ("ItemAct".act = 'VOTE' AND "Item"."userId" = "ItemAct"."userId"))
|
||||
AND "ItemAct".created_at > now_utc() - INTERVAL '1 day'`
|
||||
|
||||
// calculate the total trust
|
||||
const { sum: { trust } } = await models.user.aggregate({
|
||||
sum: {
|
||||
trust: true
|
||||
}
|
||||
})
|
||||
/*
|
||||
How earnings work:
|
||||
1/3: top 21 posts over last 36 hours, scored on a relative basis
|
||||
1/3: top 21 comments over last 36 hours, scored on a relative basis
|
||||
1/3: top upvoters of top posts/comments, scored on:
|
||||
- their trust
|
||||
- how much they tipped
|
||||
- how early they upvoted it
|
||||
- how the post/comment scored
|
||||
*/
|
||||
|
||||
// get earners { id, earnings }
|
||||
const earners = await models.$queryRaw(`
|
||||
SELECT id, FLOOR(${sum} * (trust/${trust}) * 1000) as earnings
|
||||
FROM users
|
||||
WHERE trust > 0`)
|
||||
WITH item_ratios AS (
|
||||
SELECT *,
|
||||
"weightedVotes"/(sum("weightedVotes") OVER (PARTITION BY "parentId" IS NULL)) AS ratio
|
||||
FROM (
|
||||
SELECT *,
|
||||
ROW_NUMBER() OVER (PARTITION BY "parentId" IS NULL ORDER BY "weightedVotes" desc) AS r
|
||||
FROM
|
||||
"Item"
|
||||
WHERE created_at >= now_utc() - interval '36 hours'
|
||||
) x
|
||||
WHERE x.r <= ${TOP_ITEMS}
|
||||
),
|
||||
upvoters AS (
|
||||
SELECT "ItemAct"."userId", item_ratios.id, item_ratios.ratio, item_ratios."parentId",
|
||||
sum("ItemAct".sats) as tipped, min("ItemAct".created_at) as acted_at
|
||||
FROM item_ratios
|
||||
JOIN "ItemAct" on "ItemAct"."itemId" = item_ratios.id
|
||||
WHERE act IN ('VOTE','TIP')
|
||||
AND "ItemAct"."userId" <> item_ratios."userId"
|
||||
GROUP BY "ItemAct"."userId", item_ratios.id, item_ratios.ratio, item_ratios."parentId"
|
||||
),
|
||||
upvoter_ratios AS (
|
||||
SELECT "userId", sum(early_multiplier*tipped_ratio*ratio*users.trust) as upvoting_score,
|
||||
"parentId" IS NULL as "isPost"
|
||||
FROM (
|
||||
SELECT *,
|
||||
${EARLY_MULTIPLIER_MAX}/(ROW_NUMBER() OVER (partition by id order by acted_at asc)) AS early_multiplier,
|
||||
tipped::float/(sum(tipped) OVER (partition by id)) tipped_ratio
|
||||
FROM upvoters
|
||||
) u
|
||||
JOIN users on "userId" = users.id
|
||||
GROUP BY "userId", "parentId" IS NULL
|
||||
)
|
||||
SELECT "userId" as id, FLOOR(sum(proportion)*${sum}*1000) as earnings
|
||||
FROM (
|
||||
SELECT "userId",
|
||||
upvoting_score/(sum(upvoting_score) OVER (PARTITION BY "isPost"))/${UPVOTE_EACH_REWARD} as proportion
|
||||
FROM upvoter_ratios
|
||||
UNION ALL
|
||||
SELECT "userId", ratio/${ITEM_EACH_REWARD} as proportion
|
||||
FROM item_ratios
|
||||
) a
|
||||
GROUP BY "userId"
|
||||
HAVING FLOOR(sum(proportion)*${sum}) >= 1`)
|
||||
|
||||
// for each earner, serialize earnings
|
||||
// we do this for each earner because we don't need to serialize
|
||||
|
@ -41,47 +91,4 @@ function earn ({ models }) {
|
|||
}
|
||||
}
|
||||
|
||||
// earn historical ... TODO: delete after announcement
|
||||
function earnHistorical ({ models }) {
|
||||
return async function ({ name }) {
|
||||
console.log('running', name)
|
||||
|
||||
// compute how much sn earned today
|
||||
const [{ sum }] = await models.$queryRaw`
|
||||
SELECT sum("ItemAct".sats)
|
||||
FROM "ItemAct"
|
||||
JOIN "Item" on "ItemAct"."itemId" = "Item".id
|
||||
WHERE ("ItemAct".act in ('BOOST', 'STREAM')
|
||||
OR ("ItemAct".act = 'VOTE' AND "Item"."userId" = "ItemAct"."userId"))`
|
||||
|
||||
// add in the job sats that weren't recorded from jobs
|
||||
const fullSum = 200000 + sum
|
||||
|
||||
// calculate the total trust
|
||||
const { sum: { trust } } = await models.user.aggregate({
|
||||
sum: {
|
||||
trust: true
|
||||
}
|
||||
})
|
||||
|
||||
// get earners { id, earnings }
|
||||
const earners = await models.$queryRaw(`
|
||||
SELECT id, FLOOR(${fullSum} * (trust/${trust}) * 1000) as earnings
|
||||
FROM users
|
||||
WHERE trust > 0`)
|
||||
|
||||
// for each earner, serialize earnings
|
||||
// we do this for each earner because we don't need to serialize
|
||||
// all earner updates together
|
||||
earners.forEach(async earner => {
|
||||
if (earner.earnings > 0) {
|
||||
await serialize(models,
|
||||
models.$executeRaw`SELECT earn(${earner.id}, ${earner.earnings})`)
|
||||
}
|
||||
})
|
||||
|
||||
console.log('done', name)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { earn, earnHistorical }
|
||||
module.exports = { earn }
|
||||
|
|
|
@ -6,7 +6,7 @@ const { checkInvoice, checkWithdrawal } = require('./wallet')
|
|||
const { repin } = require('./repin')
|
||||
const { trust } = require('./trust')
|
||||
const { auction } = require('./auction')
|
||||
const { earn, earnHistorical } = require('./earn')
|
||||
const { earn } = require('./earn')
|
||||
const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client')
|
||||
const { indexItem, indexAllItems } = require('./search')
|
||||
const fetch = require('cross-fetch')
|
||||
|
@ -45,7 +45,6 @@ async function work () {
|
|||
await boss.work('indexAllItems', indexAllItems(args))
|
||||
await boss.work('auction', auction(args))
|
||||
await boss.work('earn', earn(args))
|
||||
await boss.work('earnHistorical', earnHistorical(args))
|
||||
|
||||
console.log('working jobs')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue