rewards only go to top posts/comments
This commit is contained in:
parent
58c1980786
commit
a40eb642a0
|
@ -2,6 +2,7 @@ import { GraphQLError } from 'graphql'
|
||||||
import { amountSchema, ssValidate } from '../../lib/validate'
|
import { amountSchema, ssValidate } from '../../lib/validate'
|
||||||
import serialize from './serial'
|
import serialize from './serial'
|
||||||
import { ANON_USER_ID } from '../../lib/constants'
|
import { ANON_USER_ID } from '../../lib/constants'
|
||||||
|
import { getItem } from './item'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
|
@ -59,7 +60,7 @@ export default {
|
||||||
SELECT coalesce(sum(sats), 0) as total, json_agg("Earn".*) as rewards
|
SELECT coalesce(sum(sats), 0) as total, json_agg("Earn".*) as rewards
|
||||||
FROM day_cte
|
FROM day_cte
|
||||||
CROSS JOIN LATERAL (
|
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"
|
FROM "Earn"
|
||||||
WHERE "Earn"."userId" = ${me.id}
|
WHERE "Earn"."userId" = ${me.id}
|
||||||
AND date_trunc('day', "Earn".created_at AT TIME ZONE 'UTC' AT TIME ZONE 'America/Chicago') = day_cte.day
|
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
|
return sats
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Reward: {
|
||||||
|
item: async (reward, args, { me, models }) => {
|
||||||
|
if (!reward.typeId) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return getItem(reward, { id: reward.typeId }, { me, models })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ export default gql`
|
||||||
type: String
|
type: String
|
||||||
rank: Int
|
rank: Int
|
||||||
sats: Int!
|
sats: Int!
|
||||||
|
item: Item
|
||||||
}
|
}
|
||||||
|
|
||||||
type MeRewards {
|
type MeRewards {
|
||||||
|
|
|
@ -40,13 +40,7 @@ export default function Items ({ ssrData, variables = {}, query, destructureData
|
||||||
{items.filter(filter).map((item, i) => (
|
{items.filter(filter).map((item, i) => (
|
||||||
<Fragment key={item.id}>
|
<Fragment key={item.id}>
|
||||||
{pinMap && pinMap[i + 1] && <Item item={pinMap[i + 1]} />}
|
{pinMap && pinMap[i + 1] && <Item item={pinMap[i + 1]} />}
|
||||||
{item.parentId
|
<ListItem item={item} rank={rank && i + 1} siblingComments={variables.includeComments} />
|
||||||
? <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} />))}
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</div>
|
</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 }) {
|
export function ItemsSkeleton ({ rank, startRank = 0, limit = LIMIT }) {
|
||||||
const items = new Array(limit).fill(null)
|
const items = new Array(limit).fill(null)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
import { ITEM_FULL_FIELDS } from './items'
|
||||||
|
|
||||||
export const REWARDS = gql`
|
export const REWARDS = gql`
|
||||||
query rewards($when: String) {
|
query rewards($when: String) {
|
||||||
|
@ -13,6 +14,7 @@ export const REWARDS = gql`
|
||||||
}`
|
}`
|
||||||
|
|
||||||
export const ME_REWARDS = gql`
|
export const ME_REWARDS = gql`
|
||||||
|
${ITEM_FULL_FIELDS}
|
||||||
query meRewards($when: String) {
|
query meRewards($when: String) {
|
||||||
rewards(when: $when) {
|
rewards(when: $when) {
|
||||||
total
|
total
|
||||||
|
@ -28,6 +30,10 @@ export const ME_REWARDS = gql`
|
||||||
type
|
type
|
||||||
rank
|
rank
|
||||||
sats
|
sats
|
||||||
|
item {
|
||||||
|
...ItemFullFields
|
||||||
|
text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { useRouter } from 'next/router'
|
||||||
import { getGetServerSideProps } from '../../api/ssrApollo'
|
import { getGetServerSideProps } from '../../api/ssrApollo'
|
||||||
import { fixedDecimal } from '../../lib/format'
|
import { fixedDecimal } from '../../lib/format'
|
||||||
import Trophy from '../../svgs/trophy-fill.svg'
|
import Trophy from '../../svgs/trophy-fill.svg'
|
||||||
|
import { ListItem } from '../../components/items'
|
||||||
|
|
||||||
const GrowthPieChart = dynamic(() => import('../../components/charts').then(mod => mod.GrowthPieChart), {
|
const GrowthPieChart = dynamic(() => import('../../components/charts').then(mod => mod.GrowthPieChart), {
|
||||||
loading: () => <div>Loading...</div>
|
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
|
if (!rank) return null
|
||||||
|
|
||||||
const color = rank <= 3 ? 'text-primary' : 'text-muted'
|
const color = rank <= 3 ? 'text-primary' : 'text-muted'
|
||||||
|
@ -73,8 +74,14 @@ function Reward ({ rank, type, sats }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={color}>
|
<div>
|
||||||
<Trophy height={20} width={20} /> <b>#{rank}</b> {category} for <i><b>{sats} sats</b></i>
|
<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>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ function earn ({ models }) {
|
||||||
- how early they upvoted it
|
- how early they upvoted it
|
||||||
- how the post/comment scored
|
- 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 }
|
// get earners { userId, id, type, rank, proportion }
|
||||||
|
@ -118,11 +118,9 @@ function earn ({ models }) {
|
||||||
JOIN users on "userId" = users.id
|
JOIN users on "userId" = users.id
|
||||||
GROUP BY "userId", "parentId" IS NULL
|
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,
|
SELECT "userId", id, type, rank, ratio/2.0 as proportion
|
||||||
upvoter_ratio/(sum(upvoter_ratio) OVER (PARTITION BY "isPost"))/2 as proportion
|
FROM item_ratios
|
||||||
FROM upvoter_ratios
|
ORDER BY type, rank ASC`
|
||||||
WHERE upvoter_ratio > 0
|
|
||||||
ORDER BY "isPost", rank ASC`
|
|
||||||
|
|
||||||
// in order to group earnings for users we use the same createdAt time for
|
// in order to group earnings for users we use the same createdAt time for
|
||||||
// all earnings
|
// all earnings
|
||||||
|
|
Loading…
Reference in New Issue