Achievements: generator-driven, now 100+ across 7 categories (added Rulership)
mirrored client + server with identical ids/goals/coins. New tracked stats:
hakemRounds (be the hakem — incl. "7× Hakem"), roundsWon, plus losses metric.
Custom achievement-only sticker packs (Rulership 👑, Firestorm 🔥) with new
inline-SVG art (crown-gold, seven-zip, streak-fire), unlocked by hakem_7 /
streak_10. Server GameRoom tallies hakem rounds per seat + rounds won per team;
client tallies the same for vs-computer/private games (dealId-deduped).
Forfeit (surrender): a player can request forfeit; if the teammate is a bot it
auto-confirms, otherwise the human teammate gets a confirm/decline prompt
(20s timeout). Result: forfeiting with ≥1 round won = normal loss; 0 rounds = Kot.
Wired client↔server over the hub (RequestForfeit/ConfirmForfeit/DeclineForfeit
+ "forfeit" event); offline/vs-computer ends immediately in the store. Flag
button + confirm dialogs in the table.
Online count: never shows below 50 — live service floors the real count with a
drifting believable number (mock base lowered to ~50–170).
Matchmaking: real players get a longer priority window (9s) before bots fill;
bots now occasionally react after winning a trick (humanize).
Coins: starter pack is 95,000 Toman (50k coins); packs rescaled up (server + mock).
Verified: dotnet build + tsc + next build clean; sim unlocks 57 achievements/500
matches; live server: starter=95000, a 7-hakem win unlocks hakem_7 + wins_1 with
hakemRounds/roundsWon persisted. Images rebuilt on :1500/:1505.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
{id:"first_win",category:"victory",metric:"wins",goal: 1,coinReward: 100,icon:"🥇",nameFa:"اولین برد",nameEn:"First Win",descFa:"اولین بازی خود را ببرید",descEn:"Win your first game"},
{id:"wins_10",category:"victory",metric:"wins",goal: 10,coinReward: 300,icon:"🎯",nameFa:"۱۰ برد",nameEn:"10 Wins",descFa:"۱۰ بازی ببرید",descEn:"Win 10 games"},
{id:"wins_25",category:"victory",metric:"wins",goal: 25,coinReward: 600,icon:"🏅",nameFa:"۲۵ برد",nameEn:"25 Wins",descFa:"۲۵ بازی ببرید",descEn:"Win 25 games"},
{id:"wins_50",category:"victory",metric:"wins",goal: 50,coinReward: 1000,icon:"🏆",nameFa:"۵۰ برد",nameEn:"50 Wins",descFa:"۵۰ بازی ببرید",descEn:"Win 50 games"},
{id:"wins_100",category:"victory",metric:"wins",goal: 100,coinReward: 2000,icon:"👑",nameFa:"۱۰۰ برد",nameEn:"100 Wins",descFa:"۱۰۰ بازی ببرید (پک استیکر ایرانی)",descEn:"Win 100 games (unlocks Persian stickers)"},
{id:"wins_250",category:"victory",metric:"wins",goal: 250,coinReward: 4000,icon:"💎",nameFa:"۲۵۰ برد",nameEn:"250 Wins",descFa:"۲۵۰ بازی ببرید",descEn:"Win 250 games"},
{id:"wins_500",category:"victory",metric:"wins",goal: 500,coinReward: 8000,icon:"🌟",nameFa:"۵۰۰ برد",nameEn:"500 Wins",descFa:"۵۰۰ بازی ببرید",descEn:"Win 500 games"},
{id:"shutout_1",category:"victory",metric:"shutoutWins",goal: 1,coinReward: 400,icon:"🧹",nameFa:"هفت–هیچ",nameEn:"Seven–Zip",descFa:"بازی را ۷–۰ ببرید (پک استیکر حکم)",descEn:"Win a match 7–0 (unlocks Hokm stickers)"},
{id:"shutout_5",category:"victory",metric:"shutoutWins",goal: 5,coinReward: 900,icon:"🧨",nameFa:"۵ بار هفت–هیچ",nameEn:"5× Sweep",descFa:"۵ بار حریف را ۷–۰ ببرید",descEn:"Sweep the opponent 5 times"},
{id:"shutout_25",category:"victory",metric:"shutoutWins",goal: 25,coinReward: 3000,icon:"☄️",nameFa:"۲۵ بار هفت–هیچ",nameEn:"25× Sweep",descFa:"۲۵ بار حریف را ۷–۰ ببرید",descEn:"Sweep the opponent 25 times"},
// ---- Kot ----
{id:"first_kot",category:"kot",metric:"kotsFor",goal: 1,coinReward: 150,icon:"🔥",nameFa:"اولین کُت",nameEn:"First Kot",descFa:"یک بار حریف را کُت کنید",descEn:"Inflict a Kot once"},
{id:"kot_5",category:"kot",metric:"kotsFor",goal: 5,coinReward: 300,icon:"🌶️",nameFa:"۵ کُت",nameEn:"5 Kots",descFa:"۵ بار حریف را کُت کنید",descEn:"Inflict 5 Kots"},
{id:"kot_10",category:"kot",metric:"kotsFor",goal: 10,coinReward: 500,icon:"🔥",nameFa:"۱۰ کُت",nameEn:"10 Kots",descFa:"۱۰ بار حریف را کُت کنید",descEn:"Inflict 10 Kots"},
{id:"kot_25",category:"kot",metric:"kotsFor",goal: 25,coinReward: 1200,icon:"💥",nameFa:"۲۵ کُت",nameEn:"25 Kots",descFa:"۲۵ بار حریف را کُت کنید (پک استیکر طعنه)",descEn:"Inflict 25 Kots (unlocks Taunt stickers)"},
{id:"kot_50",category:"kot",metric:"kotsFor",goal: 50,coinReward: 2500,icon:"⚡",nameFa:"۵۰ کُت",nameEn:"50 Kots",descFa:"۵۰ بار حریف را کُت کنید",descEn:"Inflict 50 Kots"},
{id:"kot_100",category:"kot",metric:"kotsFor",goal: 100,coinReward: 5000,icon:"👹",nameFa:"۱۰۰ کُت",nameEn:"100 Kots",descFa:"۱۰۰ بار حریف را کُت کنید",descEn:"Inflict 100 Kots"},
// ---- Streaks ----
{id:"streak_3",category:"streak",metric:"bestWinStreak",goal: 3,coinReward: 200,icon:"➡️",nameFa:"۳ برد پیاپی",nameEn:"3 Win Streak",descFa:"۳ بازی پشت سر هم ببرید",descEn:"Win 3 games in a row"},
{id:"streak_5",category:"streak",metric:"bestWinStreak",goal: 5,coinReward: 400,icon:"⚡",nameFa:"۵ برد پیاپی",nameEn:"5 Win Streak",descFa:"۵ بازی پشت سر هم ببرید",descEn:"Win 5 games in a row"},
{id:"streak_10",category:"streak",metric:"bestWinStreak",goal: 10,coinReward: 1000,icon:"🌊",nameFa:"۱۰ برد پیاپی",nameEn:"10 Win Streak",descFa:"۱۰ بازی پشت سر هم ببرید",descEn:"Win 10 games in a row"},
{id:"streak_15",category:"streak",metric:"bestWinStreak",goal: 15,coinReward: 2000,icon:"🚀",nameFa:"۱۵ برد پیاپی",nameEn:"15 Win Streak",descFa:"۱۵ بازی پشت سر هم ببرید",descEn:"Win 15 games in a row"},
// ---- Levels (every 5) ----
{id:"level_5",category:"level",metric:"level",goal: 5,coinReward: 150,icon:"⭐",nameFa:"سطح ۵",nameEn:"Level 5",descFa:"به سطح ۵ برسید",descEn:"Reach level 5"},
{id:"level_10",category:"level",metric:"level",goal: 10,coinReward: 300,icon:"🌟",nameFa:"سطح ۱۰",nameEn:"Level 10",descFa:"به سطح ۱۰ برسید",descEn:"Reach level 10"},
{id:"level_15",category:"level",metric:"level",goal: 15,coinReward: 500,icon:"✨",nameFa:"سطح ۱۵",nameEn:"Level 15",descFa:"به سطح ۱۵ برسید",descEn:"Reach level 15"},
{id:"level_20",category:"level",metric:"level",goal: 20,coinReward: 800,icon:"💫",nameFa:"سطح ۲۰",nameEn:"Level 20",descFa:"به سطح ۲۰ برسید",descEn:"Reach level 20"},
{id:"level_25",category:"level",metric:"level",goal: 25,coinReward: 1200,icon:"🔆",nameFa:"سطح ۲۵",nameEn:"Level 25",descFa:"به سطح ۲۵ برسید (آپلود عکس باز میشود)",descEn:"Reach level 25 (unlocks photo upload)"},
{id:"level_30",category:"level",metric:"level",goal: 30,coinReward: 1600,icon:"🎖️",nameFa:"سطح ۳۰",nameEn:"Level 30",descFa:"به سطح ۳۰ برسید",descEn:"Reach level 30"},
{id:"level_40",category:"level",metric:"level",goal: 40,coinReward: 2500,icon:"🏵️",nameFa:"سطح ۴۰",nameEn:"Level 40",descFa:"به سطح ۴۰ برسید",descEn:"Reach level 40"},
{id:"level_50",category:"level",metric:"level",goal: 50,coinReward: 4000,icon:"🌠",nameFa:"سطح ۵۰",nameEn:"Level 50",descFa:"به سطح ۵۰ برسید",descEn:"Reach level 50"},
{id:"games_10",category:"veteran",metric:"games",goal: 10,coinReward: 150,icon:"🎮",nameFa:"۱۰ بازی",nameEn:"10 Games",descFa:"۱۰ بازی انجام دهید",descEn:"Play 10 games"},
{id:"games_50",category:"veteran",metric:"games",goal: 50,coinReward: 350,icon:"🕹️",nameFa:"۵۰ بازی",nameEn:"50 Games",descFa:"۵۰ بازی انجام دهید",descEn:"Play 50 games"},
{id:"games_200",category:"veteran",metric:"games",goal: 200,coinReward: 1200,icon:"🎲",nameFa:"۲۰۰ بازی",nameEn:"200 Games",descFa:"۲۰۰ بازی انجام دهید",descEn:"Play 200 games"},
{id:"games_500",category:"veteran",metric:"games",goal: 500,coinReward: 3000,icon:"🃏",nameFa:"۵۰۰ بازی",nameEn:"500 Games",descFa:"۵۰۰ بازی انجام دهید",descEn:"Play 500 games"},
{id:"games_1000",category:"veteran",metric:"games",goal: 1000,coinReward: 7000,icon:"♾️",nameFa:"۱۰۰۰ بازی",nameEn:"1000 Games",descFa:"۱۰۰۰ بازی انجام دهید",descEn:"Play 1000 games"},
{id:"tricks_100",category:"veteran",metric:"tricks",goal: 100,coinReward: 300,icon:"🎴",nameFa:"۱۰۰ دست",nameEn:"100 Tricks",descFa:"۱۰۰ دست ببرید",descEn:"Win 100 tricks"},
{id:"tricks_1000",category:"veteran",metric:"tricks",goal: 1000,coinReward: 2000,icon:"🗂️",nameFa:"۱۰۰۰ دست",nameEn:"1000 Tricks",descFa:"۱۰۰۰ دست ببرید",descEn:"Win 1000 tricks"},
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.