rewards only go to top posts/comments

This commit is contained in:
keyan 2023-08-29 16:05:09 -05:00
parent 58c1980786
commit a40eb642a0
6 changed files with 45 additions and 17 deletions

View File

@ -2,6 +2,7 @@ import { GraphQLError } from 'graphql'
import { amountSchema, ssValidate } from '../../lib/validate'
import serialize from './serial'
import { ANON_USER_ID } from '../../lib/constants'
import { getItem } from './item'
export default {
Query: {
@ -59,7 +60,7 @@ export default {
SELECT coalesce(sum(sats), 0) as total, json_agg("Earn".*) as rewards
FROM day_cte
CROSS JOIN LATERAL (
(SELECT FLOOR("Earn".msats / 1000.0) as sats, type, rank
(SELECT FLOOR("Earn".msats / 1000.0) as sats, type, rank, "typeId"
FROM "Earn"
WHERE "Earn"."userId" = ${me.id}
AND date_trunc('day', "Earn".created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago') = day_cte.day
@ -84,5 +85,14 @@ export default {
return sats
}
},
Reward: {
item: async (reward, args, { me, models }) => {
if (!reward.typeId) {
return null
}
return getItem(reward, { id: reward.typeId }, { me, models })
}
}
}

View File

@ -20,6 +20,7 @@ export default gql`
type: String
rank: Int
sats: Int!
item: Item
}
type MeRewards {

View File

@ -40,13 +40,7 @@ export default function Items ({ ssrData, variables = {}, query, destructureData
{items.filter(filter).map((item, i) => (
<Fragment key={item.id}>
{pinMap && pinMap[i + 1] && <Item item={pinMap[i + 1]} />}
{item.parentId
? <CommentFlat item={item} rank={rank && i + 1} noReply includeParent clickToContext />
: (item.isJob
? <ItemJob item={item} rank={rank && i + 1} />
: (item.searchText
? <ItemFull item={item} rank={rank && i + 1} noReply siblingComments={variables.includeComments} />
: <Item item={item} rank={rank && i + 1} siblingComments={variables.includeComments} />))}
<ListItem item={item} rank={rank && i + 1} siblingComments={variables.includeComments} />
</Fragment>
))}
</div>
@ -59,6 +53,18 @@ export default function Items ({ ssrData, variables = {}, query, destructureData
)
}
export function ListItem ({ item, ...props }) {
return (
item.parentId
? <CommentFlat item={item} noReply includeParent clickToContext {...props} />
: (item.isJob
? <ItemJob item={item} />
: (item.searchText
? <ItemFull item={item} noReply {...props} />
: <Item item={item} {...props} />))
)
}
export function ItemsSkeleton ({ rank, startRank = 0, limit = LIMIT }) {
const items = new Array(limit).fill(null)

View File

@ -1,4 +1,5 @@
import gql from 'graphql-tag'
import { ITEM_FULL_FIELDS } from './items'
export const REWARDS = gql`
query rewards($when: String) {
@ -13,6 +14,7 @@ export const REWARDS = gql`
}`
export const ME_REWARDS = gql`
${ITEM_FULL_FIELDS}
query meRewards($when: String) {
rewards(when: $when) {
total
@ -28,6 +30,10 @@ export const ME_REWARDS = gql`
type
rank
sats
item {
...ItemFullFields
text
}
}
}
}`

View File

@ -7,6 +7,7 @@ import { useRouter } from 'next/router'
import { getGetServerSideProps } from '../../api/ssrApollo'
import { fixedDecimal } from '../../lib/format'
import Trophy from '../../svgs/trophy-fill.svg'
import { ListItem } from '../../components/items'
const GrowthPieChart = dynamic(() => import('../../components/charts').then(mod => mod.GrowthPieChart), {
loading: () => <div>Loading...</div>
@ -51,7 +52,7 @@ export default function Rewards ({ ssrData }) {
)
}
function Reward ({ rank, type, sats }) {
function Reward ({ rank, type, sats, item }) {
if (!rank) return null
const color = rank <= 3 ? 'text-primary' : 'text-muted'
@ -73,8 +74,14 @@ function Reward ({ rank, type, sats }) {
}
return (
<div>
<div className={color}>
<Trophy height={20} width={20} /> <b>#{rank}</b> {category} for <i><b>{sats} sats</b></i>
</div>
{item &&
<div className={item.parentId ? 'pt-0' : 'pt-2'}>
<ListItem item={item} />
</div>}
</div>
)
}

View File

@ -65,7 +65,7 @@ function earn ({ models }) {
- how early they upvoted it
- how the post/comment scored
Now: 100% of earnings go to zappers of the top 21% of posts/comments
Now: 100% of earnings go to top 21% of posts/comments
*/
// get earners { userId, id, type, rank, proportion }
@ -118,11 +118,9 @@ function earn ({ models }) {
JOIN users on "userId" = users.id
GROUP BY "userId", "parentId" IS NULL
)
SELECT "userId", NULL as id, type, ROW_NUMBER() OVER (PARTITION BY "isPost" ORDER BY upvoter_ratio DESC) as rank,
upvoter_ratio/(sum(upvoter_ratio) OVER (PARTITION BY "isPost"))/2 as proportion
FROM upvoter_ratios
WHERE upvoter_ratio > 0
ORDER BY "isPost", rank ASC`
SELECT "userId", id, type, rank, ratio/2.0 as proportion
FROM item_ratios
ORDER BY type, rank ASC`
// in order to group earnings for users we use the same createdAt time for
// all earnings