dubs-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/.claude/settings.local.json +280 -0
  2. package/CLAUDE.md +46 -0
  3. package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
  4. package/CURRENT_SESSION.md +171 -0
  5. package/CURRENT_SESSION_DRAW.md +516 -0
  6. package/MARCH_MADNESS_SURVIVOR.md +254 -0
  7. package/PANDA.md +166 -0
  8. package/Procfile +4 -0
  9. package/README.md +476 -0
  10. package/controllers/livescoresController.js +376 -0
  11. package/controllers/pickemController.js +554 -0
  12. package/controllers/survivorAdminController.js +887 -0
  13. package/controllers/survivorController.js +623 -0
  14. package/cron/oracleMonitor.js +77 -0
  15. package/cron/pickemOracleMonitor.js +73 -0
  16. package/data/jackpot-history.json +952 -0
  17. package/data/ncaaTeams.js +406 -0
  18. package/documentation/API_SECURITY_GUIDE.md +327 -0
  19. package/documentation/ARCADE_API.md +593 -0
  20. package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
  21. package/documentation/ARCADE_QUICKSTART.md +242 -0
  22. package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
  23. package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
  24. package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
  25. package/documentation/CLAIM_STATUS_FIX.md +67 -0
  26. package/documentation/CLI_TOOL_GUIDE.md +372 -0
  27. package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
  28. package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
  29. package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
  30. package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
  31. package/documentation/DATABASE_QUERIES.md +269 -0
  32. package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
  33. package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
  34. package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
  35. package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
  36. package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
  37. package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
  38. package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
  39. package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
  40. package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
  41. package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
  42. package/documentation/HEROKU_DEPLOYMENT.md +134 -0
  43. package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
  44. package/documentation/JACKPOT_API.md +521 -0
  45. package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
  46. package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
  47. package/documentation/JWT_QUICK_SETUP.md +268 -0
  48. package/documentation/JWT_TESTING_GUIDE.md +404 -0
  49. package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
  50. package/documentation/KEEPER_SETUP.md +206 -0
  51. package/documentation/KEEPER_STATE_MACHINE.md +423 -0
  52. package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
  53. package/documentation/LOCAL_VOTING_TEST.md +279 -0
  54. package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
  55. package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
  56. package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
  57. package/documentation/PNL_TRACKING_SETUP.md +189 -0
  58. package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
  59. package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
  60. package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
  61. package/documentation/QUICK_AUTH_SETUP.md +99 -0
  62. package/documentation/QUICK_DEPLOY.md +224 -0
  63. package/documentation/QUICK_FIX.md +114 -0
  64. package/documentation/QUICK_START.md +152 -0
  65. package/documentation/REFEREE_MODE_GUIDE.md +392 -0
  66. package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
  67. package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
  68. package/documentation/RUN_MIGRATION_NOW.md +39 -0
  69. package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
  70. package/documentation/SETUP_GUIDE.md +184 -0
  71. package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
  72. package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
  73. package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
  74. package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
  75. package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
  76. package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
  77. package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
  78. package/ecosystem.config.js +65 -0
  79. package/env.template +125 -0
  80. package/middleware/apiKeyAuth.js +136 -0
  81. package/middleware/authenticate.js +214 -0
  82. package/middleware/developerUserAuth.js +76 -0
  83. package/middleware/socketAuth.js +69 -0
  84. package/package.json +49 -0
  85. package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
  86. package/postman/Dubs-API-v1.postman_collection.json +205 -0
  87. package/postman/Dubs_Developer_API.postman_collection.json +662 -0
  88. package/postman/QUICKSTART.md +118 -0
  89. package/postman/QUICK_REFERENCE.md +246 -0
  90. package/postman/README.md +71 -0
  91. package/postman/VOTING_API_GUIDE.md +426 -0
  92. package/refactor/Animations.md +148 -0
  93. package/refactor/Chat.md +252 -0
  94. package/routes/actionsRoutes.js +699 -0
  95. package/routes/adminRoutes.js +370 -0
  96. package/routes/analyticsRoutes.js +1262 -0
  97. package/routes/arcadeRoutes.js +557 -0
  98. package/routes/authRoutes.js +2310 -0
  99. package/routes/avatarRoutes.js +85 -0
  100. package/routes/botRoutes.js +211 -0
  101. package/routes/chatRoutes.js +377 -0
  102. package/routes/cryptoPriceRoutes.js +105 -0
  103. package/routes/developerRoutes.js +4201 -0
  104. package/routes/deviceRoutes.js +214 -0
  105. package/routes/dmRoutes.js +167 -0
  106. package/routes/esportsRoutes.js +806 -0
  107. package/routes/exchangeRateRoutes.js +233 -0
  108. package/routes/gamesRoutes.js +3028 -0
  109. package/routes/jackpotRoutes.js +754 -0
  110. package/routes/keeperMonitoringRoutes.js +156 -0
  111. package/routes/keeperWebhookRoutes.js +466 -0
  112. package/routes/livescoresRoutes.js +31 -0
  113. package/routes/pickemAdminRoutes.js +199 -0
  114. package/routes/pickemRoutes.js +231 -0
  115. package/routes/playerStatsRoutes.js +147 -0
  116. package/routes/portfolioRoutes.js +217 -0
  117. package/routes/promoRoutes.js +418 -0
  118. package/routes/referralEarningsRoutes.js +392 -0
  119. package/routes/socialRoutes.js +459 -0
  120. package/routes/sportsRoutes.js +1271 -0
  121. package/routes/survivorAdminRoutes.js +345 -0
  122. package/routes/survivorRoutes.js +756 -0
  123. package/routes/uploadRoutes.js +256 -0
  124. package/routes/userProfileRoutes.js +244 -0
  125. package/routes/whatsNewRoutes.js +331 -0
  126. package/scripts/.claude/settings.local.json +15 -0
  127. package/scripts/README.md +170 -0
  128. package/scripts/RESTART_EVERYTHING.sh +104 -0
  129. package/scripts/add-claim-columns.sql +48 -0
  130. package/scripts/add-crypto-prices-cache.sql +27 -0
  131. package/scripts/add-exchange-rates-cache.sql +40 -0
  132. package/scripts/add-game-invite-column.sql +23 -0
  133. package/scripts/add-game-invite-notification.sql +33 -0
  134. package/scripts/add-game-invite-telegram-pref.sql +16 -0
  135. package/scripts/add-game-joined-notification.sql +16 -0
  136. package/scripts/add-game-joined-pref.js +40 -0
  137. package/scripts/add-game-joined-preference.sql +6 -0
  138. package/scripts/add-game-start-notifications.sql +41 -0
  139. package/scripts/add-notification-flags-to-games.sql +55 -0
  140. package/scripts/add-pending-game-dismissals.sql +19 -0
  141. package/scripts/add-preferred-currency.sql +34 -0
  142. package/scripts/add-winner-columns.js +61 -0
  143. package/scripts/add_mention_system.sql +53 -0
  144. package/scripts/add_payment_system.sql +96 -0
  145. package/scripts/add_sports_event_id_column.sql +22 -0
  146. package/scripts/analyze-cohort-data-heroku.js +276 -0
  147. package/scripts/analyze-cohort-data.js +295 -0
  148. package/scripts/analyze-prod-cohorts.sh +10 -0
  149. package/scripts/backfill-matchup-images.js +245 -0
  150. package/scripts/backfill-missing-signatures.js +175 -0
  151. package/scripts/backfill-referral-earnings.js +202 -0
  152. package/scripts/check-chat-schema.js +130 -0
  153. package/scripts/check-db.sh +14 -0
  154. package/scripts/check_oracle_in_game.js +54 -0
  155. package/scripts/cleanup-database.js +193 -0
  156. package/scripts/clear-notification-cache.js +85 -0
  157. package/scripts/convert-mnemonic.js +50 -0
  158. package/scripts/create-users-table.sql +44 -0
  159. package/scripts/debug-cohort-counts.js +248 -0
  160. package/scripts/debug-winner-calc.js +84 -0
  161. package/scripts/deploy-payment-system.sh +118 -0
  162. package/scripts/deploy-to-heroku.sh +63 -0
  163. package/scripts/diagnose-locked-round.js +143 -0
  164. package/scripts/dubs-cli.js +720 -0
  165. package/scripts/dump-account.js +65 -0
  166. package/scripts/find-vrf-offset.js +48 -0
  167. package/scripts/fix-chat-notifications-constraint.sql +122 -0
  168. package/scripts/fix-claim-columns.js +124 -0
  169. package/scripts/fix-constraint-now.js +44 -0
  170. package/scripts/fix-lock-timestamps.js +96 -0
  171. package/scripts/fix-locked-round.sh +126 -0
  172. package/scripts/fix-missing-badges.sql +91 -0
  173. package/scripts/fix-payment-notifications.sql +41 -0
  174. package/scripts/force-new-round.js +55 -0
  175. package/scripts/force-resolve-and-claim.js +278 -0
  176. package/scripts/important/README.md +115 -0
  177. package/scripts/important/authority-force-lock.js +197 -0
  178. package/scripts/important/authority-resolve-game.js +267 -0
  179. package/scripts/important/check-game-status.js +373 -0
  180. package/scripts/important/list-pending-games-by-version.js +270 -0
  181. package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
  182. package/scripts/initialize-jackpot.js +111 -0
  183. package/scripts/jackpot/.claude/settings.local.json +10 -0
  184. package/scripts/jackpot/force-reset.js +84 -0
  185. package/scripts/jackpot/initialize-mainnet.js +100 -0
  186. package/scripts/jackpot/keeper.js +742 -0
  187. package/scripts/jackpot/status.js +107 -0
  188. package/scripts/jackpot/update-round-duration.js +143 -0
  189. package/scripts/keeper-bot.js +112 -0
  190. package/scripts/list-pending-games.js +131 -0
  191. package/scripts/migrate-chat-v2.js +127 -0
  192. package/scripts/migrate-chat-winners.js +84 -0
  193. package/scripts/migrate-chat.sh +17 -0
  194. package/scripts/migrate-game-invite.js +83 -0
  195. package/scripts/migrate-heroku-game-notifications.sh +159 -0
  196. package/scripts/migrations/001_analytics_tables.sql +422 -0
  197. package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
  198. package/scripts/migrations/003_referral_earnings.sql +208 -0
  199. package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
  200. package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
  201. package/scripts/migrations/005_push_notifications.sql +55 -0
  202. package/scripts/migrations/006_add_draw_team_players.sql +28 -0
  203. package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
  204. package/scripts/migrations/007_add_gif_url.sql +8 -0
  205. package/scripts/migrations/008_add_connect4_columns.sql +139 -0
  206. package/scripts/migrations/008_add_pool_tracking.sql +22 -0
  207. package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
  208. package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
  209. package/scripts/migrations/011_create_developer_tables.sql +67 -0
  210. package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
  211. package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
  212. package/scripts/migrations/013_add_network_mode.sql +18 -0
  213. package/scripts/migrations/014_create_developer_app_users.sql +19 -0
  214. package/scripts/migrations/015_add_ui_config.sql +4 -0
  215. package/scripts/migrations/016_add_resolution_secret.sql +4 -0
  216. package/scripts/migrations/017_add_external_game_id.sql +3 -0
  217. package/scripts/migrations/018_create_pickem_tables.sql +115 -0
  218. package/scripts/migrations/019_expo_push_tokens.sql +19 -0
  219. package/scripts/migrations/create_whats_new_tables.sql +88 -0
  220. package/scripts/migrations/drop_live_games_tables.sql +34 -0
  221. package/scripts/open-jackpot-round.js +85 -0
  222. package/scripts/purge-all-data.sh +329 -0
  223. package/scripts/purge-all-data.sql +142 -0
  224. package/scripts/purge-heroku-data.sh +149 -0
  225. package/scripts/purge-heroku-data.sql +62 -0
  226. package/scripts/rebuild-heroku-database.sh +113 -0
  227. package/scripts/recover-funds.js +357 -0
  228. package/scripts/regenerate-epl-images.js +278 -0
  229. package/scripts/resize-s3-matchup-images.js +374 -0
  230. package/scripts/resolve-direct.js +88 -0
  231. package/scripts/resolve-mock-game.js +124 -0
  232. package/scripts/resolve-pickem-game.js +55 -0
  233. package/scripts/resolve-round-manual.js +83 -0
  234. package/scripts/resolve-stuck-game.js +382 -0
  235. package/scripts/resolve-stuck-round.js +42 -0
  236. package/scripts/run-connect4-migration.sh +16 -0
  237. package/scripts/run-mention-migration.sh +32 -0
  238. package/scripts/run-payment-migration.sh +51 -0
  239. package/scripts/run-preferred-currency-migration.sh +31 -0
  240. package/scripts/run-referral-earnings-migration.sh +32 -0
  241. package/scripts/run-survivor-outcome-migration.sh +16 -0
  242. package/scripts/seed-test-users.js +346 -0
  243. package/scripts/setup-auth-tables.js +78 -0
  244. package/scripts/setup-complete-database.sql +992 -0
  245. package/scripts/setup-database-fresh.sh +359 -0
  246. package/scripts/setup-heroku-keeper.sh +48 -0
  247. package/scripts/setup-keeper-database.js +83 -0
  248. package/scripts/setup-keeper-state-db.sql +110 -0
  249. package/scripts/setup-oracle.sh +39 -0
  250. package/scripts/setup-pnl-tracking.js +111 -0
  251. package/scripts/start-devnet.sh +14 -0
  252. package/scripts/test-arcade-devnet.sh +160 -0
  253. package/scripts/test-arcade-match.sh +109 -0
  254. package/scripts/test-automatic-mode.sh +239 -0
  255. package/scripts/test-connect4-cancel-claim.js +370 -0
  256. package/scripts/test-connect4-e2e.js +369 -0
  257. package/scripts/test-connect4-resolve.js +369 -0
  258. package/scripts/test-game-state-endpoint.js +136 -0
  259. package/scripts/test-invite-notification.js +86 -0
  260. package/scripts/test-jackpot-api.sh +71 -0
  261. package/scripts/test-poll-confirmation.js +267 -0
  262. package/scripts/test-resolve-game.js +271 -0
  263. package/scripts/test-resolve-signature.js +223 -0
  264. package/scripts/test-signature-preservation.js +124 -0
  265. package/scripts/test-state-machine.js +291 -0
  266. package/scripts/test-webhook-receiver.js +60 -0
  267. package/scripts/update-notification-constraint.js +52 -0
  268. package/scripts/verify-account-layout.js +145 -0
  269. package/scripts/verify-winner-algorithm.js +278 -0
  270. package/server.js +5259 -0
  271. package/services/arcadeMatchService.js +763 -0
  272. package/services/automaticGameOracle.js +1596 -0
  273. package/services/chatService.js +1612 -0
  274. package/services/connect4GameService.js +1049 -0
  275. package/services/connect4NotificationService.js +374 -0
  276. package/services/cryptoPriceService.js +223 -0
  277. package/services/customGameResolver.js +260 -0
  278. package/services/db.js +79 -0
  279. package/services/directMessageService.js +389 -0
  280. package/services/discordNotifications.js +160 -0
  281. package/services/exchangeRateService.js +289 -0
  282. package/services/expoPushService.js +314 -0
  283. package/services/gamesCacheService.js +539 -0
  284. package/services/jackpotHistory.js +331 -0
  285. package/services/jackpotService.js +856 -0
  286. package/services/keeperStateService.js +355 -0
  287. package/services/matchupImageService.js +591 -0
  288. package/services/notificationCacheService.js +407 -0
  289. package/services/pickemOracle.js +440 -0
  290. package/services/playerStatsService.js +389 -0
  291. package/services/portfolioService.js +555 -0
  292. package/services/promoService.js +757 -0
  293. package/services/promoTreasuryService.js +239 -0
  294. package/services/pushNotifications.js +353 -0
  295. package/services/redisService.js +422 -0
  296. package/services/referralEarningsService.js +728 -0
  297. package/services/s3Service.js +396 -0
  298. package/services/socialService.js +1202 -0
  299. package/services/survivorOracle.js +469 -0
  300. package/services/survivorSimulator.js +475 -0
  301. package/services/telegramNotifications.js +461 -0
  302. package/services/userProfileStatsService.js +1185 -0
  303. package/services/whatsNewService.js +388 -0
  304. package/utils/urlHelper.js +95 -0
@@ -0,0 +1,254 @@
1
+ # March Madness Survivor Pool - Development Notes
2
+
3
+ **Last Updated:** February 4, 2026 (Late night session - bracket connectors complete!)
4
+ **Status:** In Development (Core features working)
5
+
6
+ ## Feature Flag
7
+
8
+ In `dubs-jackpot-spa/app/v2/page.tsx`:
9
+ ```javascript
10
+ const ENABLE_MARCH_MADNESS = true; // Set to false to hide tab
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Overview
16
+
17
+ A "Survive or Die" pool where:
18
+ - Users pay **once** to join (SOL entry fee)
19
+ - Pick **ONE team per round** to win
20
+ - If your team **loses** → you're **eliminated**
21
+ - **Last survivors split the pot**
22
+
23
+ ---
24
+
25
+ ## What's Been Built
26
+
27
+ ### Backend (dubs-server)
28
+
29
+ | File | Purpose |
30
+ |------|---------|
31
+ | `routes/survivorRoutes.js` | All API endpoints for survivor pools |
32
+ | `controllers/survivorController.js` | Business logic (create pool, join, pick, resolve) |
33
+ | `services/survivorSimulator.js` | Dev testing - mock teams, simulate rounds |
34
+ | `services/survivorOracle.js` | Production - fetch ESPN results, resolve picks |
35
+
36
+ ### Frontend (dubs-jackpot-spa)
37
+
38
+ | File | Purpose |
39
+ |------|---------|
40
+ | `app/v2/features/survivor/components/SurvivorTabContent.tsx` | Main UI - pools list, pool detail, picks |
41
+ | `app/v2/features/survivor/components/bracket/BracketView.tsx` | Full tournament bracket visualization |
42
+ | `app/v2/features/survivor/components/bracket/BracketRegion.tsx` | Single region (16 teams → Elite 8) |
43
+ | `app/v2/features/survivor/components/bracket/BracketMatchup.tsx` | Single game slot (2 teams) |
44
+ | `app/v2/features/survivor/services/survivorService.ts` | API client for survivor endpoints |
45
+ | `app/v2/features/survivor/types/survivor-types.ts` | TypeScript interfaces |
46
+
47
+ ### Database Tables
48
+
49
+ ```sql
50
+ survivor_pools -- Pool settings (buy-in, current round, status)
51
+ survivor_entries -- User entries (is_alive, eliminated_at_round)
52
+ survivor_picks -- User picks per round (team, result)
53
+ survivor_tournament_games -- All tournament matchups (teams, scores, winner)
54
+ ```
55
+
56
+ ---
57
+
58
+ ## How Teams/Bracket Data Works
59
+
60
+ ### Current Setup (Development/Testing)
61
+
62
+ Teams are **hardcoded mock data** in `survivorSimulator.js`:
63
+
64
+ ```javascript
65
+ const MOCK_TEAMS = [
66
+ // 68 teams total (64 + 4 First Four)
67
+ { id: 'e1', name: 'Duke', seed: 1, region: 'EAST', logo: espnLogo(150) },
68
+ { id: 'w1', name: 'Florida', seed: 1, region: 'WEST', logo: espnLogo(57) },
69
+ { id: 's1', name: 'Auburn', seed: 1, region: 'SOUTH', logo: espnLogo(2) },
70
+ { id: 'm1', name: 'Houston', seed: 1, region: 'MIDWEST', logo: espnLogo(248) },
71
+ // ... etc
72
+ ];
73
+ ```
74
+
75
+ **To generate bracket for testing:**
76
+ ```bash
77
+ curl -X POST http://localhost:3001/api/survivor/dev/pools/1/generate-bracket
78
+ ```
79
+
80
+ This creates Round of 64 games with standard seeding matchups (1v16, 8v9, 5v12, etc.)
81
+
82
+ ### Production (Real Tournament)
83
+
84
+ After **Selection Sunday** (NCAA announces bracket):
85
+
86
+ 1. **Option A:** Import from ESPN API
87
+ 2. **Option B:** Admin uploads official bracket JSON
88
+ 3. **Option C:** Manual database entry
89
+
90
+ The bracket structure (seeding matchups) is always the same - only team names change.
91
+
92
+ ---
93
+
94
+ ## User Flow
95
+
96
+ ```
97
+ 1. JOIN POOL
98
+ └── User pays SOL entry fee → entry created
99
+
100
+ 2. MAKE PICK (each round)
101
+ └── Select one team to win → pick saved
102
+ └── Can change pick until deadline
103
+
104
+ 3. ROUND RESOLVES
105
+ └── Oracle checks ESPN for final scores
106
+ └── Winners advance, losers eliminated
107
+
108
+ 4. PAYOUT
109
+ └── After Championship, survivors split pot
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Key API Endpoints
115
+
116
+ ### Public
117
+ - `GET /api/survivor/pools` - List all pools
118
+ - `GET /api/survivor/pools/:id` - Pool details
119
+ - `GET /api/survivor/pools/:id/games` - Tournament games
120
+ - `GET /api/survivor/pools/:id/alive` - Surviving entries
121
+ - `GET /api/survivor/pools/:id/eliminated` - Eliminated entries
122
+
123
+ ### Authenticated (require JWT)
124
+ - `POST /api/survivor/pools/:id/join` - Join pool
125
+ - `GET /api/survivor/pools/:id/my-entry` - User's entry + picks
126
+ - `GET /api/survivor/pools/:id/teams` - Available teams to pick
127
+ - `POST /api/survivor/pools/:id/pick` - Submit pick
128
+
129
+ ### Dev/Simulation (development only)
130
+ - `POST /api/survivor/dev/pools/:id/generate-bracket` - Create mock bracket
131
+ - `POST /api/survivor/dev/pools/:id/simulate-round` - Random results
132
+ - `POST /api/survivor/dev/pools/:id/activate` - Set pool to active
133
+ - `POST /api/survivor/dev/pools/:id/reset` - Reset to round 1
134
+
135
+ ---
136
+
137
+ ## Bracket View Features
138
+
139
+ - **4 Regions:** South, West (left side) | East, Midwest (right side)
140
+ - **Rounds:** R64 → R32 → Sweet 16 → Elite 8 → Final Four → Championship
141
+ - **Zoom controls:** Scale 40% - 120% (default 75%)
142
+ - **Round labels:** Each column has its own label (Round of 64, Round of 32, Sweet 16, Elite 8) that aligns with the bracket
143
+ - **Connecting lines:**
144
+ - SVG lines between rounds within each region showing bracket flow
145
+ - Horizontal yellow lines from Elite 8 → Final Four (using `flex-1` to stretch)
146
+ - Vertical yellow lines from Final Four → Championship (absolutely positioned)
147
+ - **Right side mirroring:** EAST/MIDWEST regions mirrored with `scaleX(-1)` so bracket flows toward center, but text flipped back to readable
148
+ - **Final Four/Championship layout:**
149
+ - FF1 (top) connects SOUTH and EAST Elite 8 winners
150
+ - FF2 (bottom) connects WEST and MIDWEST Elite 8 winners
151
+ - Championship in center with vertical connectors from both Final Four games
152
+ - Vertical connector heights: FF1→Champ = 250px, FF2→Champ = 310px
153
+ - **Visual states:**
154
+ - Green highlight = winner
155
+ - Grayed out = eliminated
156
+ - Red pulse = live game
157
+ - "TBD" = future matchup
158
+ - Yellow lines = Final Four/Championship connectors
159
+
160
+ ---
161
+
162
+ ## Testing Commands
163
+
164
+ ```bash
165
+ # Create a test pool
166
+ curl -X POST http://localhost:3001/api/survivor/pools \
167
+ -H "Content-Type: application/json" \
168
+ -d '{"name":"Test Pool 2025","year":2025,"buyInLamports":"100000000"}'
169
+
170
+ # Generate bracket for pool ID 1
171
+ curl -X POST http://localhost:3001/api/survivor/dev/pools/1/generate-bracket
172
+
173
+ # Activate pool (move to round 2)
174
+ curl -X POST http://localhost:3001/api/survivor/dev/pools/1/activate
175
+
176
+ # Simulate round with 20% upset chance
177
+ curl -X POST http://localhost:3001/api/survivor/dev/pools/1/simulate-round \
178
+ -H "Content-Type: application/json" \
179
+ -d '{"upsetChance":0.2}'
180
+ ```
181
+
182
+ ---
183
+
184
+ ## What's Left To Do
185
+
186
+ ### High Priority
187
+ - [ ] **Real bracket import** - Admin endpoint to import actual NCAA bracket after Selection Sunday
188
+ - [ ] **Round advancement** - Auto-create next round games when current round completes
189
+ - [ ] **Oracle integration** - Connect to ESPN API for live scores
190
+ - [ ] **Deadline enforcement** - Auto-eliminate users who don't pick before deadline
191
+ - [ ] **Payout logic** - Distribute pot to survivors via Solana
192
+
193
+ ### Medium Priority
194
+ - [ ] **Pick history display** - Show user's picks from previous rounds
195
+ - [ ] **Leaderboard** - Show all alive/eliminated entries
196
+ - [ ] **Notifications** - Email/push for deadlines, results
197
+ - [ ] **Multiple entries** - Allow users to buy multiple entries
198
+
199
+ ### Polish
200
+ - [x] **Bracket connector lines** - Visual lines connecting matchups ✓
201
+ - [x] **Final Four/Championship connectors** - Vertical lines connecting FF to Championship ✓
202
+ - [x] **Round column labels** - Labels aligned with each bracket column ✓
203
+ - [ ] **Mobile responsive** - Better mobile bracket view
204
+ - [ ] **Animations** - Transitions when winners revealed
205
+
206
+ ---
207
+
208
+ ## ESPN Team Logo URLs
209
+
210
+ Logos come from ESPN CDN:
211
+ ```
212
+ https://a.espncdn.com/i/teamlogos/ncaa/500/{espn_team_id}.png
213
+ ```
214
+
215
+ Example ESPN team IDs:
216
+ - Duke: 150
217
+ - Florida: 57
218
+ - Auburn: 2
219
+ - Houston: 248
220
+
221
+ Full list in `survivorSimulator.js` → `MOCK_TEAMS` array.
222
+
223
+ ---
224
+
225
+ ## Round Names
226
+
227
+ ```javascript
228
+ const ROUND_NAMES = {
229
+ 1: 'First Four',
230
+ 2: 'Round of 64',
231
+ 3: 'Round of 32',
232
+ 4: 'Sweet 16',
233
+ 5: 'Elite 8',
234
+ 6: 'Final Four',
235
+ 7: 'Championship',
236
+ };
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Questions for Tomorrow
242
+
243
+ 1. How should we import the real bracket after Selection Sunday?
244
+ 2. Should users be able to change their pick before the deadline?
245
+ 3. What happens if all remaining users pick the same losing team?
246
+ 4. Refund policy if tournament is cancelled?
247
+
248
+ ---
249
+
250
+ ## Related Files
251
+
252
+ - **Plan document:** `~/.claude/plans/glittery-leaping-cocoa.md`
253
+ - **Frontend:** `~/Developer/iheartsolana/dubs-jackpot-spa/app/v2/features/survivor/`
254
+ - **Backend:** `~/Developer/iheartsolana/solana-programs/dubs-server/`
package/PANDA.md ADDED
@@ -0,0 +1,166 @@
1
+ # PandaScore Data Structure
2
+
3
+ ## Overview
4
+
5
+ PandaScore uses an opinionated, hierarchical data structure to map esports competitions across all video games. Understanding this hierarchy is critical for building betting features on top of it.
6
+
7
+ ## Hierarchy
8
+
9
+ ```
10
+ Videogame (Valorant, CS2, LoL, Dota 2)
11
+ └── League (recurring competition — e.g. VCT Champions, ESL Pro League)
12
+ └── Series (single occurrence — e.g. VCT Champions 2026)
13
+ └── Tournament (stage — e.g. Group Stage, Playoffs)
14
+ └── Match (confrontation — e.g. Team A vs Team B)
15
+ └── Game (individual map/round)
16
+ ```
17
+
18
+ ## Levels Explained
19
+
20
+ ### Videogame
21
+ The game itself. Each has a unique ID and slug.
22
+
23
+ | ID | Name | Slug |
24
+ |----|------|------|
25
+ | 1 | League of Legends | league-of-legends |
26
+ | 3 | Counter-Strike | cs-go |
27
+ | 4 | Dota 2 | dota-2 |
28
+ | 14 | Overwatch | ow |
29
+ | 20 | PUBG | pubg |
30
+ | 22 | Rocket League | rl |
31
+ | 23 | Call of Duty | cod-mw |
32
+ | 24 | Rainbow 6 Siege | r6-siege |
33
+ | 25 | EA Sports FC | fifa |
34
+ | 26 | Valorant | valorant |
35
+ | 27 | King of Glory | kog |
36
+ | 28 | LoL Wild Rift | lol-wild-rift |
37
+ | 29 | StarCraft 2 | starcraft-2 |
38
+ | 30 | StarCraft Brood War | starcraft-brood-war |
39
+ | 34 | Mobile Legends | mlbb |
40
+
41
+ ### League
42
+ The top-level competition. Think of it as the brand/name of a recurring event.
43
+ - **Sports analogy**: FIFA World Cup, UEFA Champions League, NFL
44
+ - **Esports examples**: VCT Champions, ESL Pro League, LCK, The International
45
+
46
+ Key fields: `id`, `name`, `slug`, `image_url`, `videogame`, `series[]`
47
+
48
+ ### Series
49
+ A single timely occurrence of a league. One league has many series over the years.
50
+ - **Sports analogy**: FIFA World Cup 2022, NFL Season 2024
51
+ - **Esports examples**: VCT Champions 2026, ESL Pro League Season 21
52
+
53
+ Key fields: `id`, `full_name`, `year`, `season`, `begin_at`, `end_at`, `winner_id`, `league_id`
54
+
55
+ ### Tournament
56
+ A stage or phase within a series. This is where standings and brackets live.
57
+ - **Sports analogy**: FIFA World Cup 2022 — Group C, NFL 2024 — Playoffs
58
+ - **Esports examples**: VCT Champions 2026 — Group Stage, The International 2026 — Playoffs
59
+
60
+ Key fields: `id`, `name`, `type` (bracket type), `matches[]`, `teams[]`, `standings`
61
+
62
+ ### Match
63
+ A confrontation between two opponents. **This is the betting level** — where you have two sides and an outcome.
64
+ - **Sports analogy**: Denmark vs Australia
65
+ - **Esports examples**: OG vs PSG.LGD (best of 5)
66
+
67
+ Key fields: `id`, `name`, `status` (not_started/running/finished), `opponents[]`, `results[]`, `winner`, `begin_at`, `number_of_games`, `tournament_id`
68
+
69
+ Match statuses:
70
+ - `not_started` — scheduled, not yet live
71
+ - `running` — currently being played
72
+ - `finished` — completed with results
73
+ - `canceled` — won't happen
74
+
75
+ ### Game
76
+ An individual map or round within a match. Data structure varies per videogame.
77
+ - **Sports analogy**: A single match has one game (Denmark vs Australia = 1 game)
78
+ - **Esports examples**: A CS2 best-of-3 match has up to 3 games (maps)
79
+
80
+ Game-level data is videogame-specific and only available for games supporting Historical Data.
81
+
82
+ ## Key Differences from Traditional Sports
83
+
84
+ | Concept | Traditional Sports | Esports (PandaScore) |
85
+ |---------|-------------------|----------------------|
86
+ | Season structure | Fixed schedule (82 games, 17 weeks, etc.) | Tournament-based, variable |
87
+ | "League" means | A fixed set of teams playing a season | Any recurring competition |
88
+ | Regular season | Yes (months of scheduled games) | Rare — mostly events/tournaments |
89
+ | Betting level | Individual game in the schedule | Match (within a tournament) |
90
+ | Nesting depth | League → Season → Game | League → Series → Tournament → Match → Game |
91
+
92
+ ## For Dubs Betting
93
+
94
+ The path to a bettable event:
95
+ 1. Pick relevant **Leagues** (curate a whitelist of league IDs worth betting on)
96
+ 2. Find active **Series** within those leagues (current year/season)
97
+ 3. Get **Tournaments** within those series (group stage, playoffs, etc.)
98
+ 4. List **Matches** within those tournaments — these are what users bet on
99
+ 5. Match `status: "not_started"` = upcoming and bettable
100
+
101
+ ## API Endpoints (Our Server)
102
+
103
+ Current endpoints at `/api/esports`:
104
+
105
+ ```
106
+ GET /api/esports/leagues — List all leagues
107
+ GET /api/esports/leagues/:leagueId — Get single league
108
+ GET /api/esports/videogames/:videogameId/leagues — Leagues by game
109
+ GET /api/esports/leagues/:id/series — Series within a league
110
+ GET /api/esports/leagues/:id/tournaments — Tournaments within a league
111
+ GET /api/esports/leagues/:id/matches/upcoming — Upcoming (bettable) matches
112
+ GET /api/esports/leagues/:id/matches/running — Currently live matches
113
+ GET /api/esports/leagues/:id/matches — All matches (rich filtering)
114
+ ```
115
+
116
+ ### Key Response Fields by Endpoint
117
+
118
+ **Series** — `full_name`, `year`, `season`, `begin_at`, `end_at`, `winner_id`, `tournaments[]`
119
+
120
+ **Tournaments** — `name`, `tier` (s/a/b/c/d/unranked), `type` (online/offline), `prizepool`, `region`, `teams[]`, `matches[]`, `expected_roster[]`, `begin_at`, `end_at`
121
+
122
+ **Matches** — `name`, `status`, `opponents[]`, `results[]`, `winner`, `begin_at`, `number_of_games`, `match_type` (best_of), `tournament`, `streams_list[]`, `games[]`, `live.url` (WebSocket), `serie`, `rescheduled`, `forfeit`, `draw`, `videogame_title`
123
+
124
+ ### Match Filtering (General `/matches` Endpoint)
125
+
126
+ The general matches endpoint supports powerful filtering:
127
+ - `filter[status]=running` — Live matches only
128
+ - `filter[status]=not_started` — Upcoming only
129
+ - `filter[status]=finished` — Completed only
130
+ - `filter[future]=true` — Future matches (by begin_at)
131
+ - `filter[past]=true` — Past matches
132
+ - `filter[opponent_id]=123` — Matches involving a specific team/player
133
+ - `filter[tournament_id]=456` — Matches in a specific tournament
134
+ - `filter[serie_id]=789` — Matches in a specific series
135
+ - `filter[opponents_filled]=true` — Only matches with known opponents (not TBD)
136
+ - `filter[match_type]=best_of` — Filter by match format
137
+ - `range[begin_at]=2026-01-01,2026-12-31` — Date range filter
138
+ - `sort=-scheduled_at` — Sort by scheduled date (descending)
139
+
140
+ ## API Authentication
141
+
142
+ PandaScore uses Bearer token auth:
143
+ ```
144
+ Authorization: Bearer <PANDASCORE_API_KEY>
145
+ ```
146
+
147
+ Environment variable: `PANDASCORE_API_KEY`
148
+
149
+ ## Pagination
150
+
151
+ All list endpoints support:
152
+ - `page` — page number (default: 1)
153
+ - `per_page` — results per page (default: 50, max: 100)
154
+ - `sort` — field to sort by (prefix with `-` for descending, e.g. `-modified_at`)
155
+
156
+ ## Filtering & Search
157
+
158
+ - `filter[field]=value` — exact match filter
159
+ - `search[field]=value` — fuzzy text search
160
+ - `range[field]=min,max` — range filter
161
+
162
+ ## References
163
+
164
+ - [PandaScore API Docs](https://developers.pandascore.co/docs/introduction)
165
+ - [Data Structure Fundamentals](https://developers.pandascore.co/docs/fundamentals)
166
+ - [Filtering & Sorting](https://developers.pandascore.co/docs/filtering-and-sorting)
package/Procfile ADDED
@@ -0,0 +1,4 @@
1
+ web: node server.js
2
+ oracle: node cron/oracleMonitor.js
3
+ jackpot-keeper: node scripts/jackpot/keeper.js
4
+ pickem-oracle: node cron/pickemOracleMonitor.js