Algorithm
In a space of black-box pump bots, we show our math.
In a space of black-box pump bots, we show our math.
Every score on this platform — user grade, project reputation, community grade, network rank, achievements, conviction — comes from a formula that lives in one place in the codebase, with all weights declared as constants you can read.
No hidden boosts. No pay-to-rank. No tenant favoritism. Pro tiers unlock tools — automation, custom branding, analytics, profile cosmetics. They never buy a higher rank.
If you find a number on the platform you can't explain by reading this file, that's a bug.
User Raid Resume grade
Every user with linked activity gets a grade: S, A, B, C, D, or Unranked.
One function computes the score. One constants block declares the weights. The render layer never invents a bonus on the way to the screen.
Inputs:
- Global reputation earned across every community you've opted into (sum of per-project rules)
- Community breadth bonus — extra credit per project beyond the first you're active in
- Achievement bonus — per achievement you've earned (any type)
- Weekly win bonus — per #1 weekly leaderboard finish in any community
- Top-3 finish bonus — per top-3 weekly finish that wasn't already a #1 win
- Verified X reply bonus — per
x_reply_verifiedevent you produced - X reply speed bonus — proportional to the speed-bonus units your verified replies earned (5/3/1 units for under-5/15/30 min)
- Streak bonuses (3 / 5 / 10 in a row) — forward-compatible weights; events not emitted today, weights still apply once they are
Score → grade (live thresholds, grepped from src/bot/raidResume.ts):
| Score | Grade |
|---|---|
| 1000+ | S |
| 500–999 | A |
| 250–499 | B |
| 100–249 | C |
| 1–99 | D |
| 0 | Unranked |
All weights live in the RAID_RESUME constants and computeRaidResumeScore() in src/bot/raidResume.ts. Changing the formula is a single PR with a visible diff.
Per-project reputation and points
Each project has its own public scoring formula. REDRAW awards Middle Fingers (points) and REDRAW REP (reputation); PYONYA awards Paw Points and PYONYA REP; a brand-new community gets a sensible default set on creation that its admin can edit later.
A scoring rule attaches points + reputation values to an event action. Example default values:
mission_completed → +1 point, +10 reputation
first_10_bonus → +1 point, +5 reputation
weekly_rank_1 → +100 reputation
weekly_rank_top_3 → +50 reputation
badge_awarded → +25 reputation
x_reply_verified → +5 points, +10 reputation
REDRAW awards different numbers on the same rule set (Resist Completed mission action, etc.) — each tenant defines its own values. Both are visible in scoring_rules and identical in structure.
A user's lifetime project reputation is the sum of every enabled rule applied to that user's events for that project. Global reputation is the sum across opted-in projects only.
Every per-project breakdown on a Raid Resume is explainable: for each action you can show count × weight = subtotal, summing to the visible total.
Community grade (community health)
Every community gets a Community Grade — a measure of community health, not a sum of member grades. The formula lives in src/services/communityGradeService.ts. It's the same input the Strongest Communities page (/communities) ranks by.
Weighted blend of four normalized inputs (live weights):
| Input | Measures | Weight |
|---|---|---|
| Active member ratio | active members / total members (active = completed ≥1 mission) | 25 |
| Mission completion rate | total completions / total opens | 25 |
| Engagement consistency | distinct ISO weeks with ≥1 completion in the last 8 weeks, ÷ 8 | 20 |
| Verified activity volume | min(1, (completions + verified replies) / 200) |
30 |
Each input is in [0, 1]. The composite score is Σ (input × weight), rounded to 0–100.
Score → grade (live thresholds from letterFromScore):
| Score | Grade |
|---|---|
| 90–100 | S |
| 80–89 | A |
| 65–79 | B |
| 50–64 | C |
| 30–49 | D |
| 0–29 | F |
The "Building" floor — no hollow grades
A community must clear a minimum activity floor before it gets a letter:
- ≥ 5 total missions, AND
- ≥ 3 active members
Below the floor → status is Building. The grade renders as Building (not a letter), and the page tells you exactly which threshold isn't met yet. The raw score is still computed and used for ranking, so a Building community can still appear on the network leaderboard — but the formula is never inflated to manufacture a fake A on thin activity.
Active members are counted from missions, not chat
"Active member" means a user who completed at least one mission. Chat activity is never counted. Community analytics are calculated only from mission events. See PRIVACY.md for the full posture.
Network rank (Strongest Communities)
A community's rank on /c/:slug and on the network-wide /communities page is its position when every status='active' community is sorted by the same composite score, descending, with ties broken deterministically by internal ID. Building communities are included — a single active community correctly returns rank #1 of 1 even while Building.
Ranks 1–3 render gold; ranks 4+ render in default text — same rule as the member leaderboard top-3 highlight.
The rank is computed live from the data on every page load. It is not cached, not hand-edited, and not tenant-boosted. There are no hidden boosts — the only inputs are missions completed, active members, verified replies, weekly engagement consistency, and the streak / weekly-winner events those produce.
Achievements — deterministic, append-only, no hidden grants
The engine matches a universal achievementType and looks up the per-community display row to render a tenant-skinned label. Every award creates a user_badges row and emits a transparent reputation_event with a deterministic idempotency key — re-running the evaluator is a no-op.
There are no hidden admin grants. An admin cannot silently award an achievement to a user. The rule is enforced in code — achievementService.evaluateAndAwardAchievements() is the only award path, and the idempotency keys guarantee any award has a corresponding visible event.
Nine universal types ship today:
Project-scoped (7)
| Type | Trigger |
|---|---|
| First Blood | First mission completion in this community |
| Operator | 25 missions completed in this community |
| Kill Streak | 5 missions completed in a row in this community |
| MVP | Finished #1 on a weekly leaderboard |
| Podium | Top-3 finish on a weekly leaderboard |
| Quickdraw | Average verified-reply time under 10 min across ≥5 verified replies |
| Voice | 10 verified replies on X for this community |
Global (2)
| Type | Trigger |
|---|---|
| Multiclass | Completed missions in 3 different communities |
| Linked Up | Linked a wallet to your Dossier |
Each type has a generic display name; tenants override the label per project so the same achievement reads natively in each community — e.g. REDRAW's badge vocabulary is Tag / Tags while PYONYA's is Badge / Badges. The trigger logic itself is universal and never branches on tenant.
Conviction Score (Jeetivity) — per-community, behavior-weighted
The Jeetivity card on /u/:xHandle shows a single Conviction Score — your strongest score across all communities you participate in that have a token configured. Each community that opts in by setting their own jettonMasterAddress gets its own per-member score; the global profile surfaces the highest one, honestly labelled with the community name (e.g. "Conviction 86/100 in PYONYA").
Behavior-weighted, never balance-weighted. The score doesn't care how big your bag is — it cares whether you're holding or selling. A whale who sold half their stack ranks below a small holder who's still accumulating.
Inputs (one snapshot at a time, taken twice a day):
| Symbol | Meaning |
|---|---|
current |
Latest balance |
baseline |
Earliest balance recorded for this (user, project, jetton) |
peak |
Maximum balance ever recorded for this (user, project, jetton) |
Formula:
netPosition = current - baseline # +ve accumulating, -ve sold down
soldPercentage = peak > 0 ? max(0, (peak - current) / peak) : 0
accumulationBonus =
baseline > 0 ? clamp(0, 30, max(0, (current - baseline) / baseline) * 30)
: (current > 0 ? 30 : 0)
convictionScore = clamp(0, 100, 100 - soldPercentage * 100 + accumulationBonus)
Single-label per snapshot:
convictionScore |
Label |
|---|---|
>= 70 |
Diamond |
41–69 |
Holding |
21–40 |
Paper |
<= 20 |
Jeet |
Fairness fallbacks
The gauge always reads one of three states:
- Unknown — no wallet linked, OR no community you're in has a token configured. The dot stays centered. Wallet linking is optional; this is the default state for most users.
- Insufficient Data — wallet linked, community has a token configured, but fewer than 3 snapshots exist. Same fairness rule as the Community Grade floor: never label users on thin data.
- A real label (Diamond / Holding / Paper / Jeet) — only after enough on-chain history exists.
No pay-to-rank
Conviction is computed from balance-over-time, not from balance size at a single moment. A user can't buy in the morning, snapshot, and call themselves Diamond. The score is computed across the full series of snapshots (peak / baseline / current) so a one-day spike doesn't move the long-term label. DEX trades, impermanent transfers, and off-chain CEX balances are excluded — we only read on-chain balance at snapshot time.
Where to read the source
| Concern | File |
|---|---|
| Conviction formula | src/services/jeetivityService.ts (computeConviction) |
| Snapshot writer | src/services/jeetivityService.ts (snapshotMember) |
| Twice-daily worker | src/jobs/jeetivitySnapshotWorker.ts |
| Public render | src/web/publicRender.ts (jeetivityBlock) |
What is not in any score
- chat message counts
- time-of-day chat activity
- online/offline inference
- private DM contents
- sentiment from general chat
- hidden admin adjustments
- Pro-tier rank boosts (Pro buys tools and cosmetics, never rank)
- tenant favoritism:
grep -rn "pyonya\|redraw" src/services/returns zero slug branches in any score function
Where to read the source
| Formula | File |
|---|---|
| User Raid Resume grade | src/bot/raidResume.ts |
| Per-project reputation rules | seeded into scoring_rules; read by src/bot/raidResume.ts |
| Community grade + rank | src/services/communityGradeService.ts |
| Strongest Communities ranking | src/services/communityGradeService.ts (rankAllCommunities) |
| Achievement trigger logic | src/services/achievementService.ts |
| Conviction Score (Jeetivity) | src/services/jeetivityService.ts |
| Per-mission X verification | src/services/verificationService.ts |
If you find a behavior that disagrees with this file, the disagreement is a bug.
Other reputation bots ship a number. We ship the function that produces it.