From 3afb5367c1af71b561dc47a18c0f275cca21276f Mon Sep 17 00:00:00 2001 From: Obay Rashad Date: Sat, 7 Feb 2026 06:13:55 +0200 Subject: [PATCH 1/3] implemented a streak system --- sw-dash/prisma/schema.prisma | 2 + .../admin/ship_certifications/certs-view.tsx | 48 ++++++- .../admin/ship_certifications/[id]/route.ts | 135 +++++++++++++++--- sw-dash/src/lib/certs.ts | 15 +- sw-dash/src/types/index.ts | 1 + 5 files changed, 174 insertions(+), 27 deletions(-) diff --git a/sw-dash/prisma/schema.prisma b/sw-dash/prisma/schema.prisma index 28fc8f6..c4017c9 100644 --- a/sw-dash/prisma/schema.prisma +++ b/sw-dash/prisma/schema.prisma @@ -36,6 +36,8 @@ model User { cookieBalance Float @default(0) cookiesEarned Float @default(0) + streak Int @default(0) + lastReviewDate DateTime? @db.Date payoutReqs PayoutReq[] @relation("PayoutReqs") payoutApprovals PayoutReq[] @relation("PayoutApprovals") yswsReviews YswsReview[] @relation("YswsReviewer") diff --git a/sw-dash/src/app/admin/ship_certifications/certs-view.tsx b/sw-dash/src/app/admin/ship_certifications/certs-view.tsx index 614e8de..3677234 100644 --- a/sw-dash/src/app/admin/ship_certifications/certs-view.tsx +++ b/sw-dash/src/app/admin/ship_certifications/certs-view.tsx @@ -274,12 +274,34 @@ export function CertsView({ initial }: Props) { {leaderboard.length > 0 ? ( leaderboard.slice(0, 10).map((r, i) => { const change = r.rankChange + const streak = r.streak || 0 + + let streakStyle = 'border-transparent' + let streakIconColor = 'text-gray-500' + + if (streak >= 17) { + streakStyle = 'border-red-500/40 bg-gradient-to-r from-red-900/30 to-transparent' + streakIconColor = 'text-red-400' + } else if (streak >= 7) { + streakStyle = + 'border-purple-500/40 bg-gradient-to-r from-purple-900/10 to-transparent' + streakIconColor = 'text-purple-300' + } else if (streak >= 5) { + streakStyle = + 'border-blue-500/40 bg-gradient-to-r from-blue-900/10 to-transparent' + streakIconColor = 'text-blue-300' + } else if (streak >= 1) { + streakStyle = + 'border-amber-700/30 bg-gradient-to-r from-amber-900/5 to-transparent' + streakIconColor = 'text-amber-500' + } + return (
-
+
{i + 1}. {r.name} {change !== undefined && change !== 0 && ( @@ -291,7 +313,27 @@ export function CertsView({ initial }: Props) { )}
- {r.count} +
+ {streak > 0 && ( +
+ + + + {streak} +
+ )} + {r.count} +
) }) diff --git a/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts b/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts index 0248900..ba1c245 100644 --- a/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts +++ b/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts @@ -86,21 +86,21 @@ export const GET = withParams(PERMS.certs_view)(async ({ user, params }) => { const history = cert.ftProjectId ? await prisma.shipCert.findMany({ - where: { - ftProjectId: cert.ftProjectId, - id: { not: cert.id }, - status: { in: ['approved', 'rejected'] }, - }, - include: { - reviewer: { - select: { - username: true, + where: { + ftProjectId: cert.ftProjectId, + id: { not: cert.id }, + status: { in: ['approved', 'rejected'] }, + }, + include: { + reviewer: { + select: { + username: true, + }, }, }, - }, - orderBy: { reviewCompletedAt: 'desc' }, - take: 10, - }) + orderBy: { reviewCompletedAt: 'desc' }, + take: 10, + }) : [] return NextResponse.json({ @@ -124,18 +124,18 @@ export const GET = withParams(PERMS.certs_view)(async ({ user, params }) => { proofVideo: cert.proofVideoUrl, reviewer: cert.reviewer ? { - username: cert.reviewer.username, - avatar: cert.reviewer.avatar, - } + username: cert.reviewer.username, + avatar: cert.reviewer.avatar, + } : null, syncedToFt: cert.syncedToFt, assignment: cert.assignments[0] ? { - id: cert.assignments[0].id, - status: cert.assignments[0].status, - assignee: cert.assignments[0].assignee?.username || null, - createdAt: cert.assignments[0].createdAt.toISOString(), - } + id: cert.assignments[0].id, + status: cert.assignments[0].status, + assignee: cert.assignments[0].assignee?.username || null, + createdAt: cert.assignments[0].createdAt.toISOString(), + } : null, notes: internalNotes.map((note) => ({ id: note.id, @@ -290,6 +290,99 @@ export const PATCH = withParams(PERMS.certs_edit)(async ({ user, req, params, ip }) } + if (verdict) { + const getESTComponents = (date: Date) => { + const parts = new Intl.DateTimeFormat('en-US', { + timeZone: 'America/New_York', + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + hourCycle: 'h23', + }).formatToParts(date) + const getVal = (type: string) => parseInt(parts.find((p) => p.type === type)?.value || '0') + + return { + y: getVal('year'), + m: getVal('month') - 1, + d: getVal('day'), + h: getVal('hour'), + } + } + + const now = new Date() + const { y, m, d } = getESTComponents(now) + + const cand1 = new Date(Date.UTC(y, m, d, 5, 0, 0, 0)) // 5 AM UTC + const cand2 = new Date(Date.UTC(y, m, d, 4, 0, 0, 0)) // 4 AM UTC + + const check1 = getESTComponents(cand1) + + let startOfTodayUTC = cand1 + if (check1.h !== 0) { + startOfTodayUTC = cand2 + } + + const todayCount = await prisma.shipCert.count({ + where: { + reviewerId: certifierId !== undefined ? certifierId : user.id, + status: { in: ['approved', 'rejected'] }, + reviewCompletedAt: { + gte: startOfTodayUTC, + }, + }, + }) + + if (todayCount >= 7) { + const userIdToUpdate = certifierId !== undefined ? certifierId : user.id + const currentUser = await prisma.user.findUnique({ + where: { id: userIdToUpdate }, + select: { streak: true, lastReviewDate: true }, + }) + + if (currentUser) { + let newStreak = currentUser.streak + let shouldUpdate = false + + const todayNormalized = new Date(Date.UTC(y, m, d)) + const yesterdayNormalized = new Date(todayNormalized) + yesterdayNormalized.setDate(yesterdayNormalized.getDate() - 1) + + let lastReviewNormalized = null + if (currentUser.lastReviewDate) { + const ld = currentUser.lastReviewDate + + lastReviewNormalized = new Date( + Date.UTC(ld.getUTCFullYear(), ld.getUTCMonth(), ld.getUTCDate()) + ) + } + + if ( + !lastReviewNormalized || + lastReviewNormalized.getTime() < yesterdayNormalized.getTime() + ) { + newStreak = 1 + shouldUpdate = true + } else if (lastReviewNormalized.getTime() === yesterdayNormalized.getTime()) { + newStreak += 1 + shouldUpdate = true + } else if (lastReviewNormalized.getTime() === todayNormalized.getTime()) { + shouldUpdate = false + } + + if (shouldUpdate) { + await prisma.user.update({ + where: { id: userIdToUpdate }, + data: { + streak: newStreak, + lastReviewDate: todayNormalized, + }, + }) + } + } + } + } + if ( verdict && (verdict.toLowerCase() === 'approved' || diff --git a/sw-dash/src/lib/certs.ts b/sw-dash/src/lib/certs.ts index 65b08dc..8a467d9 100644 --- a/sw-dash/src/lib/certs.ts +++ b/sw-dash/src/lib/certs.ts @@ -29,6 +29,7 @@ type LeaderRow = { username: string | null currentCount: bigint prevCount: bigint + streak?: number } type TypeGroup = { @@ -106,6 +107,7 @@ async function fetchStats(lbMode: string) { SELECT sc.reviewerId AS reviewerId, u.username AS username, + u.streak AS streak, SUM(CASE WHEN sc.reviewCompletedAt >= ${weekStart} AND sc.reviewCompletedAt < ${weekEnd} THEN 1 ELSE 0 END) AS currentCount, SUM(CASE WHEN sc.reviewCompletedAt >= ${weekStart} AND sc.reviewCompletedAt < ${yesterdayEndUTC} THEN 1 ELSE 0 END) AS prevCount FROM ship_certs sc @@ -114,12 +116,13 @@ async function fetchStats(lbMode: string) { AND sc.status IN ('approved', 'rejected') AND sc.reviewCompletedAt >= ${weekStart} AND sc.reviewCompletedAt < ${weekEnd} - GROUP BY sc.reviewerId, u.username + GROUP BY sc.reviewerId, u.username, u.streak ` : prisma.$queryRaw` SELECT sc.reviewerId AS reviewerId, u.username AS username, + u.streak AS streak, COUNT(*) AS currentCount, SUM(CASE WHEN sc.reviewCompletedAt < ${yesterday} THEN 1 ELSE 0 END) AS prevCount FROM ship_certs sc @@ -127,7 +130,7 @@ async function fetchStats(lbMode: string) { WHERE sc.reviewerId IS NOT NULL AND sc.status IN ('approved', 'rejected') AND sc.reviewCompletedAt IS NOT NULL - GROUP BY sc.reviewerId, u.username + GROUP BY sc.reviewerId, u.username, u.streak `, ]) @@ -199,7 +202,12 @@ async function fetchStats(lbMode: string) { prevLeaderboard.forEach((r, i) => prevRankMap.set(r.id, i + 1)) const currentLeaderboard = leaderRows - .map((r) => ({ id: r.reviewerId, name: r.username || 'unknown', count: norm(r.currentCount) })) + .map((r) => ({ + id: r.reviewerId, + name: r.username || 'unknown', + count: norm(r.currentCount), + streak: r.streak || 0, + })) .filter((r) => lbMode !== 'weekly' || r.name !== 'System') .sort((a, b) => b.count - a.count) @@ -211,6 +219,7 @@ async function fetchStats(lbMode: string) { name: r.name, count: r.count, rankChange: rankChange === 0 ? undefined : rankChange, + streak: r.streak, } }) diff --git a/sw-dash/src/types/index.ts b/sw-dash/src/types/index.ts index bdc8ccc..ae0704b 100644 --- a/sw-dash/src/types/index.ts +++ b/sw-dash/src/types/index.ts @@ -47,6 +47,7 @@ export interface Reviewer { name: string count: number rankChange?: number + streak?: number } export interface ShipCert { From 385159fdf95bdb571d1e77fdee1cbbf2093473dc Mon Sep 17 00:00:00 2001 From: Obay Rashad Date: Fri, 13 Feb 2026 02:44:18 +0200 Subject: [PATCH 2/3] dynamic payouts :) --- sw-dash/src/app/admin/payouts/logs/page.tsx | 4 +- .../ship_certifications/mystats/page.tsx | 109 ++++++--- .../admin/ship_certifications/[id]/route.ts | 13 +- sw-dash/src/components/admin/chart.tsx | 222 +++++++++--------- sw-dash/src/lib/payouts.ts | 162 +++++++++++-- 5 files changed, 345 insertions(+), 165 deletions(-) diff --git a/sw-dash/src/app/admin/payouts/logs/page.tsx b/sw-dash/src/app/admin/payouts/logs/page.tsx index 4125ec3..7d5e8b4 100644 --- a/sw-dash/src/app/admin/payouts/logs/page.tsx +++ b/sw-dash/src/app/admin/payouts/logs/page.tsx @@ -58,8 +58,8 @@ export default async function Logs() { project reviewer type - rate - multi + base rate + eff. multi when cookies diff --git a/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx b/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx index 7f29e2b..4a19e23 100644 --- a/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx +++ b/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx @@ -225,42 +225,89 @@ export default async function Stats() {
-
-

Bounty Rates

-
- {Object.entries(RATES) - .sort((a, b) => b[1] - a[1]) - .map(([type, bounty]) => ( -
- {type} - {bounty} 🍪 -
- ))} +
+
+

+ Dynamic Payouts +

-
-
Multipliers
-
-
- 1st on lb: - 1.75x bounty -
-
- 2nd on lb: - 1.5x bounty -
-
- 3rd on lb: - 1.25x bounty + +
+
+

+ Base Rates +

+
+
+ Desktop, Mobile, Other + 1.5 🍪 +
+
+ CLI, Games, Hardware + 1.0 🍪 +
+
+ Web Apps, Bots + 0.6 🍪 +
-
- 4th+ on lb: - 1x bounty +
+ +
+

+ Multipliers +

+
+
+
+ + First Review + + + 1.5x for your 1st review of the day + +
+ 1.5x +
+
+
+ + Old Projects + + + 1.5x if >7 days, 1.2x if >24h + +
+ 1.5x +
+
+
+ Daily Grind + + 1.2x after 7 reviews, 1.3x after 15 + +
+ 1.3x +
+
+
+ Weekly Rank + + 1.75x (1st), 1.5x (2nd), 1.25x (3rd) + +
+ 1.75x +
+ +
+

+ Base × Multipliers = Total.{' '} + Max 6.0 🍪 +

+
diff --git a/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts b/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts index d46b82b..c0073d6 100644 --- a/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts +++ b/sw-dash/src/app/api/admin/ship_certifications/[id]/route.ts @@ -235,9 +235,18 @@ export const PATCH = withParams(PERMS.certs_edit)(async ({ user, req, params, ip } if (verdict.toLowerCase() === 'approved' || verdict.toLowerCase() === 'rejected') { - const payout = await calc(user.id, cert.projectType, cert.customBounty) + const payout = await calc({ + userId: user.id, + projectType: cert.projectType, + verdict: verdict.toLowerCase() as 'approved' | 'rejected', + certCreatedAt: cert.createdAt, + customBounty: cert.customBounty, + }) updateData.cookiesEarned = payout.cookies - updateData.payoutMulti = payout.multi + + const effectiveMulti = + payout.base > 0 ? (payout.cookies - (payout.customBounty || 0)) / payout.base : 0 + updateData.payoutMulti = Number(effectiveMulti.toFixed(2)) } } diff --git a/sw-dash/src/components/admin/chart.tsx b/sw-dash/src/components/admin/chart.tsx index 58e5383..d705a81 100644 --- a/sw-dash/src/components/admin/chart.tsx +++ b/sw-dash/src/components/admin/chart.tsx @@ -1,128 +1,128 @@ 'use client' import { - LineChart, - Line, - BarChart, - Bar, - XAxis, - YAxis, - Tooltip, - ResponsiveContainer, - CartesianGrid, + LineChart, + Line, + BarChart, + Bar, + XAxis, + YAxis, + Tooltip, + ResponsiveContainer, + CartesianGrid, } from 'recharts' interface Props { - data: Array<{ date?: string; label?: string; value: number;[key: string]: any }> - type?: 'line' | 'bar' - dataKey?: string - xKey?: string - yLabel?: string - xLabel?: string - valueLabel?: string - color?: string + data: Array<{ date?: string; label?: string; value: number; [key: string]: any }> + type?: 'line' | 'bar' + dataKey?: string + xKey?: string + yLabel?: string + xLabel?: string + valueLabel?: string + color?: string } export function Chart({ - data, - type = 'line', - dataKey = 'value', - xKey = 'date', - yLabel = 'Value', - xLabel = 'Date', - valueLabel = 'Value', - color = '#f59e0b', + data, + type = 'line', + dataKey = 'value', + xKey = 'date', + yLabel = 'Value', + xLabel = 'Date', + valueLabel = 'Value', + color = '#f59e0b', }: Props) { - const formatDate = (dateStr: string) => { - const date = new Date(dateStr) - const month = date.toLocaleString('en-US', { month: 'short' }) - const day = date.getDate() - return `${month} ${day}` - } + const formatDate = (dateStr: string) => { + const date = new Date(dateStr) + const month = date.toLocaleString('en-US', { month: 'short' }) + const day = date.getDate() + return `${month} ${day}` + } - const CustomTooltip = ({ active, payload }: any) => { - if (!active || !payload || !payload.length) return null + const CustomTooltip = ({ active, payload }: any) => { + if (!active || !payload || !payload.length) return null - const date = payload[0].payload[xKey] - const value = payload[0].value + const date = payload[0].payload[xKey] + const value = payload[0].value - return ( -
-

- {date ? formatDate(date) : ''} -

-

- {valueLabel}: {value} -

-
- ) - } + return ( +
+

+ {date ? formatDate(date) : ''} +

+

+ {valueLabel}: {value} +

+
+ ) + } - const formatXAxis = (value: string) => { - return formatDate(value) - } + const formatXAxis = (value: string) => { + return formatDate(value) + } - return ( - - {type === 'line' ? ( - - - - - } cursor={false} /> + return ( + + {type === 'line' ? ( + + + + + } cursor={false} /> - - ) : ( - - - - - } cursor={false} /> - - - )} - - ) + + ) : ( + + + + + } cursor={false} /> + + + )} + + ) } diff --git a/sw-dash/src/lib/payouts.ts b/sw-dash/src/lib/payouts.ts index 4173fb6..c9a6cdc 100644 --- a/sw-dash/src/lib/payouts.ts +++ b/sw-dash/src/lib/payouts.ts @@ -1,31 +1,81 @@ import { prisma } from './db' const RATES: Record = { - 'Web App': 0.75, - 'Chat Bot': 0.75, - Extension: 0.94, + 'Desktop App (Windows)': 1.5, + 'Desktop App (Linux)': 1.5, + 'Desktop App (macOS)': 1.5, + 'Android App': 1.5, + 'iOS App': 1.5, + Other: 1.5, CLI: 1, Cargo: 1, - 'Desktop App (Windows)': 1.25, 'Minecraft Mods': 1, - 'Android App': 1, - 'iOS App': 1, 'Steam Games': 1, PyPI: 1, - 'Desktop App (Linux)': 1.4, - 'Desktop App (macOS)': 1.4, - Hardware: 1.4, - Other: 1.4, + Hardware: 1, + Extension: 1, + 'Web App': 0.6, + 'Chat Bot': 0.6, } -const MULTI = [1.75, 1.5, 1.25] +const RANK_MULTI = [1.75, 1.5, 1.25] +const CAP = 6 export function getBounty(type: string | null): number { if (!type) return 1 return RATES[type] ?? 1 } -export async function getMulti(userId: number): Promise { +function getESTComponents(date: Date) { + const parts = new Intl.DateTimeFormat('en-US', { + timeZone: 'America/New_York', + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: 'numeric', + hourCycle: 'h23', + }).formatToParts(date) + const getVal = (type: string) => parseInt(parts.find((p) => p.type === type)?.value || '0') + return { y: getVal('year'), m: getVal('month') - 1, d: getVal('day'), h: getVal('hour') } +} + +function getStartOfTodayUTC(): Date { + const now = new Date() + const { y, m, d } = getESTComponents(now) + const cand1 = new Date(Date.UTC(y, m, d, 5, 0, 0, 0)) + const cand2 = new Date(Date.UTC(y, m, d, 4, 0, 0, 0)) + const check1 = getESTComponents(cand1) + return check1.h !== 0 ? cand2 : cand1 +} + +type WaitTier = 'new' | 'normal' | 'old' | 'ancient' + +function classifyWait(createdAt: Date): WaitTier { + const ageMs = Date.now() - createdAt.getTime() + const ageH = ageMs / (1000 * 60 * 60) + if (ageH < 8) return 'new' + if (ageH <= 24) return 'normal' + if (ageH <= 7 * 24) return 'old' + return 'ancient' +} + +async function getWaitMulti(tier: WaitTier): Promise { + if (tier === 'normal') return 1 + if (tier === 'old') return 1.2 + if (tier === 'ancient') return 1.5 + + // For "new" projects, only penalise if there are ≥ 7 old/ancient pending + const eightHoursAgo = new Date(Date.now() - 8 * 60 * 60 * 1000) + const oldCount = await prisma.shipCert.count({ + where: { + status: 'pending', + createdAt: { lt: eightHoursAgo }, + }, + }) + return oldCount >= 7 ? 0.8 : 1 +} + +async function getRankMulti(userId: number): Promise { const now = new Date() const day = now.getDay() const weekStart = new Date(now) @@ -62,16 +112,90 @@ export async function getMulti(userId: number): Promise { const pos = lb.findIndex((r) => r.reviewerId === userId) if (pos < 0) return 1 - if (pos < 3) return MULTI[pos] + if (pos < 3) return RANK_MULTI[pos] return 1 } -export async function calc(userId: number, type: string | null, customBounty?: number | null) { - const bounty = getBounty(type) - const multi = await getMulti(userId) - const base = bounty * multi - const total = customBounty ? base + customBounty : base - return { cookies: total, multi, bounty, customBounty: customBounty || 0 } +async function getStreakMulti(userId: number): Promise { + const user = await prisma.user.findUnique({ + where: { id: userId }, + select: { streak: true }, + }) + if (!user || user.streak <= 0) return 1 + return 1 + user.streak * 0.05 +} + +async function getDailyMulti(userId: number): Promise { + const startOfToday = getStartOfTodayUTC() + + const todayCount = await prisma.shipCert.count({ + where: { + reviewerId: userId, + status: { in: ['approved', 'rejected'] }, + reviewCompletedAt: { gte: startOfToday }, + }, + }) + + if (todayCount === 0) return 1.5 // first review of the day + if (todayCount >= 15) return 1.3 + if (todayCount >= 7) return 1.2 + return 1 +} + +export interface CalcInput { + userId: number + projectType: string | null + verdict: 'approved' | 'rejected' + certCreatedAt: Date + customBounty?: number | null +} + +export interface CalcResult { + cookies: number + base: number + waitMulti: number + verdictMulti: number + rankMulti: number + streakMulti: number + dailyMulti: number + customBounty: number + capped: boolean +} + +export async function calc(input: CalcInput): Promise { + const { userId, projectType, verdict, certCreatedAt, customBounty } = input + + const base = getBounty(projectType) + + const waitTier = classifyWait(certCreatedAt) + const waitMulti = await getWaitMulti(waitTier) + + const verdictMulti = verdict === 'rejected' ? 0.8 : 1 + + const rankMulti = await getRankMulti(userId) + const streakMulti = 1 // unused for now + + const dailyMulti = await getDailyMulti(userId) + + let computed = base * waitMulti * verdictMulti * rankMulti * dailyMulti + const capped = computed > CAP + if (capped) computed = CAP + + const flat = customBounty || 0 + const total = computed + flat + + return { + cookies: total, + base, + waitMulti, + verdictMulti, + rankMulti, + streakMulti, + dailyMulti, + customBounty: flat, + capped, + } } export { RATES } +export { getRankMulti as getMulti } From 209555e26aac206af41411474180f0a1291ef0fd Mon Sep 17 00:00:00 2001 From: Obay Rashad Date: Sun, 15 Feb 2026 18:01:18 +0200 Subject: [PATCH 3/3] removed the payout cap --- sw-dash/src/app/admin/ship_certifications/mystats/page.tsx | 1 - sw-dash/src/lib/payouts.ts | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx b/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx index 4a19e23..441bd0b 100644 --- a/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx +++ b/sw-dash/src/app/admin/ship_certifications/mystats/page.tsx @@ -305,7 +305,6 @@ export default async function Stats() {

Base × Multipliers = Total.{' '} - Max 6.0 🍪

diff --git a/sw-dash/src/lib/payouts.ts b/sw-dash/src/lib/payouts.ts index c9a6cdc..ae96418 100644 --- a/sw-dash/src/lib/payouts.ts +++ b/sw-dash/src/lib/payouts.ts @@ -19,7 +19,6 @@ const RATES: Record = { } const RANK_MULTI = [1.75, 1.5, 1.25] -const CAP = 6 export function getBounty(type: string | null): number { if (!type) return 1 @@ -159,7 +158,6 @@ export interface CalcResult { streakMulti: number dailyMulti: number customBounty: number - capped: boolean } export async function calc(input: CalcInput): Promise { @@ -177,9 +175,7 @@ export async function calc(input: CalcInput): Promise { const dailyMulti = await getDailyMulti(userId) - let computed = base * waitMulti * verdictMulti * rankMulti * dailyMulti - const capped = computed > CAP - if (capped) computed = CAP + const computed = base * waitMulti * verdictMulti * rankMulti * dailyMulti const flat = customBounty || 0 const total = computed + flat @@ -193,7 +189,6 @@ export async function calc(input: CalcInput): Promise { streakMulti, dailyMulti, customBounty: flat, - capped, } }