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 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
 | 
					// TODO: use a weekly trust measure or make trust decay
 | 
				
			||||||
function earn ({ models }) {
 | 
					function earn ({ models }) {
 | 
				
			||||||
  return async function ({ name }) {
 | 
					  return async function ({ name }) {
 | 
				
			||||||
@ -14,18 +19,63 @@ function earn ({ models }) {
 | 
				
			|||||||
          OR ("ItemAct".act = 'VOTE' AND "Item"."userId" = "ItemAct"."userId"))
 | 
					          OR ("ItemAct".act = 'VOTE' AND "Item"."userId" = "ItemAct"."userId"))
 | 
				
			||||||
          AND "ItemAct".created_at > now_utc() - INTERVAL '1 day'`
 | 
					          AND "ItemAct".created_at > now_utc() - INTERVAL '1 day'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // calculate the total trust
 | 
					    /*
 | 
				
			||||||
    const { sum: { trust } } = await models.user.aggregate({
 | 
					      How earnings work:
 | 
				
			||||||
      sum: {
 | 
					      1/3: top 21 posts over last 36 hours, scored on a relative basis
 | 
				
			||||||
        trust: true
 | 
					      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 }
 | 
					    // get earners { id, earnings }
 | 
				
			||||||
    const earners = await models.$queryRaw(`
 | 
					    const earners = await models.$queryRaw(`
 | 
				
			||||||
      SELECT id, FLOOR(${sum} * (trust/${trust}) * 1000) as earnings
 | 
					      WITH item_ratios AS (
 | 
				
			||||||
      FROM users
 | 
					        SELECT *,
 | 
				
			||||||
      WHERE trust > 0`)
 | 
					            "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
 | 
					    // for each earner, serialize earnings
 | 
				
			||||||
    // we do this for each earner because we don't need to serialize
 | 
					    // 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
 | 
					module.exports = { earn }
 | 
				
			||||||
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 }
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ const { checkInvoice, checkWithdrawal } = require('./wallet')
 | 
				
			|||||||
const { repin } = require('./repin')
 | 
					const { repin } = require('./repin')
 | 
				
			||||||
const { trust } = require('./trust')
 | 
					const { trust } = require('./trust')
 | 
				
			||||||
const { auction } = require('./auction')
 | 
					const { auction } = require('./auction')
 | 
				
			||||||
const { earn, earnHistorical } = require('./earn')
 | 
					const { earn } = require('./earn')
 | 
				
			||||||
const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client')
 | 
					const { ApolloClient, HttpLink, InMemoryCache } = require('@apollo/client')
 | 
				
			||||||
const { indexItem, indexAllItems } = require('./search')
 | 
					const { indexItem, indexAllItems } = require('./search')
 | 
				
			||||||
const fetch = require('cross-fetch')
 | 
					const fetch = require('cross-fetch')
 | 
				
			||||||
@ -45,7 +45,6 @@ async function work () {
 | 
				
			|||||||
  await boss.work('indexAllItems', indexAllItems(args))
 | 
					  await boss.work('indexAllItems', indexAllItems(args))
 | 
				
			||||||
  await boss.work('auction', auction(args))
 | 
					  await boss.work('auction', auction(args))
 | 
				
			||||||
  await boss.work('earn', earn(args))
 | 
					  await boss.work('earn', earn(args))
 | 
				
			||||||
  await boss.work('earnHistorical', earnHistorical(args))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  console.log('working jobs')
 | 
					  console.log('working jobs')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user