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.
- package/.claude/settings.local.json +280 -0
- package/CLAUDE.md +46 -0
- package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
- package/CURRENT_SESSION.md +171 -0
- package/CURRENT_SESSION_DRAW.md +516 -0
- package/MARCH_MADNESS_SURVIVOR.md +254 -0
- package/PANDA.md +166 -0
- package/Procfile +4 -0
- package/README.md +476 -0
- package/controllers/livescoresController.js +376 -0
- package/controllers/pickemController.js +554 -0
- package/controllers/survivorAdminController.js +887 -0
- package/controllers/survivorController.js +623 -0
- package/cron/oracleMonitor.js +77 -0
- package/cron/pickemOracleMonitor.js +73 -0
- package/data/jackpot-history.json +952 -0
- package/data/ncaaTeams.js +406 -0
- package/documentation/API_SECURITY_GUIDE.md +327 -0
- package/documentation/ARCADE_API.md +593 -0
- package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
- package/documentation/ARCADE_QUICKSTART.md +242 -0
- package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
- package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
- package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
- package/documentation/CLAIM_STATUS_FIX.md +67 -0
- package/documentation/CLI_TOOL_GUIDE.md +372 -0
- package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
- package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
- package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
- package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
- package/documentation/DATABASE_QUERIES.md +269 -0
- package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
- package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
- package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
- package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
- package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
- package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
- package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
- package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
- package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
- package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
- package/documentation/HEROKU_DEPLOYMENT.md +134 -0
- package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
- package/documentation/JACKPOT_API.md +521 -0
- package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
- package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
- package/documentation/JWT_QUICK_SETUP.md +268 -0
- package/documentation/JWT_TESTING_GUIDE.md +404 -0
- package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
- package/documentation/KEEPER_SETUP.md +206 -0
- package/documentation/KEEPER_STATE_MACHINE.md +423 -0
- package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
- package/documentation/LOCAL_VOTING_TEST.md +279 -0
- package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
- package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
- package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
- package/documentation/PNL_TRACKING_SETUP.md +189 -0
- package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
- package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
- package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
- package/documentation/QUICK_AUTH_SETUP.md +99 -0
- package/documentation/QUICK_DEPLOY.md +224 -0
- package/documentation/QUICK_FIX.md +114 -0
- package/documentation/QUICK_START.md +152 -0
- package/documentation/REFEREE_MODE_GUIDE.md +392 -0
- package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
- package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
- package/documentation/RUN_MIGRATION_NOW.md +39 -0
- package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
- package/documentation/SETUP_GUIDE.md +184 -0
- package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
- package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
- package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
- package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
- package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
- package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
- package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
- package/ecosystem.config.js +65 -0
- package/env.template +125 -0
- package/middleware/apiKeyAuth.js +136 -0
- package/middleware/authenticate.js +214 -0
- package/middleware/developerUserAuth.js +76 -0
- package/middleware/socketAuth.js +69 -0
- package/package.json +49 -0
- package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
- package/postman/Dubs-API-v1.postman_collection.json +205 -0
- package/postman/Dubs_Developer_API.postman_collection.json +662 -0
- package/postman/QUICKSTART.md +118 -0
- package/postman/QUICK_REFERENCE.md +246 -0
- package/postman/README.md +71 -0
- package/postman/VOTING_API_GUIDE.md +426 -0
- package/refactor/Animations.md +148 -0
- package/refactor/Chat.md +252 -0
- package/routes/actionsRoutes.js +699 -0
- package/routes/adminRoutes.js +370 -0
- package/routes/analyticsRoutes.js +1262 -0
- package/routes/arcadeRoutes.js +557 -0
- package/routes/authRoutes.js +2310 -0
- package/routes/avatarRoutes.js +85 -0
- package/routes/botRoutes.js +211 -0
- package/routes/chatRoutes.js +377 -0
- package/routes/cryptoPriceRoutes.js +105 -0
- package/routes/developerRoutes.js +4201 -0
- package/routes/deviceRoutes.js +214 -0
- package/routes/dmRoutes.js +167 -0
- package/routes/esportsRoutes.js +806 -0
- package/routes/exchangeRateRoutes.js +233 -0
- package/routes/gamesRoutes.js +3028 -0
- package/routes/jackpotRoutes.js +754 -0
- package/routes/keeperMonitoringRoutes.js +156 -0
- package/routes/keeperWebhookRoutes.js +466 -0
- package/routes/livescoresRoutes.js +31 -0
- package/routes/pickemAdminRoutes.js +199 -0
- package/routes/pickemRoutes.js +231 -0
- package/routes/playerStatsRoutes.js +147 -0
- package/routes/portfolioRoutes.js +217 -0
- package/routes/promoRoutes.js +418 -0
- package/routes/referralEarningsRoutes.js +392 -0
- package/routes/socialRoutes.js +459 -0
- package/routes/sportsRoutes.js +1271 -0
- package/routes/survivorAdminRoutes.js +345 -0
- package/routes/survivorRoutes.js +756 -0
- package/routes/uploadRoutes.js +256 -0
- package/routes/userProfileRoutes.js +244 -0
- package/routes/whatsNewRoutes.js +331 -0
- package/scripts/.claude/settings.local.json +15 -0
- package/scripts/README.md +170 -0
- package/scripts/RESTART_EVERYTHING.sh +104 -0
- package/scripts/add-claim-columns.sql +48 -0
- package/scripts/add-crypto-prices-cache.sql +27 -0
- package/scripts/add-exchange-rates-cache.sql +40 -0
- package/scripts/add-game-invite-column.sql +23 -0
- package/scripts/add-game-invite-notification.sql +33 -0
- package/scripts/add-game-invite-telegram-pref.sql +16 -0
- package/scripts/add-game-joined-notification.sql +16 -0
- package/scripts/add-game-joined-pref.js +40 -0
- package/scripts/add-game-joined-preference.sql +6 -0
- package/scripts/add-game-start-notifications.sql +41 -0
- package/scripts/add-notification-flags-to-games.sql +55 -0
- package/scripts/add-pending-game-dismissals.sql +19 -0
- package/scripts/add-preferred-currency.sql +34 -0
- package/scripts/add-winner-columns.js +61 -0
- package/scripts/add_mention_system.sql +53 -0
- package/scripts/add_payment_system.sql +96 -0
- package/scripts/add_sports_event_id_column.sql +22 -0
- package/scripts/analyze-cohort-data-heroku.js +276 -0
- package/scripts/analyze-cohort-data.js +295 -0
- package/scripts/analyze-prod-cohorts.sh +10 -0
- package/scripts/backfill-matchup-images.js +245 -0
- package/scripts/backfill-missing-signatures.js +175 -0
- package/scripts/backfill-referral-earnings.js +202 -0
- package/scripts/check-chat-schema.js +130 -0
- package/scripts/check-db.sh +14 -0
- package/scripts/check_oracle_in_game.js +54 -0
- package/scripts/cleanup-database.js +193 -0
- package/scripts/clear-notification-cache.js +85 -0
- package/scripts/convert-mnemonic.js +50 -0
- package/scripts/create-users-table.sql +44 -0
- package/scripts/debug-cohort-counts.js +248 -0
- package/scripts/debug-winner-calc.js +84 -0
- package/scripts/deploy-payment-system.sh +118 -0
- package/scripts/deploy-to-heroku.sh +63 -0
- package/scripts/diagnose-locked-round.js +143 -0
- package/scripts/dubs-cli.js +720 -0
- package/scripts/dump-account.js +65 -0
- package/scripts/find-vrf-offset.js +48 -0
- package/scripts/fix-chat-notifications-constraint.sql +122 -0
- package/scripts/fix-claim-columns.js +124 -0
- package/scripts/fix-constraint-now.js +44 -0
- package/scripts/fix-lock-timestamps.js +96 -0
- package/scripts/fix-locked-round.sh +126 -0
- package/scripts/fix-missing-badges.sql +91 -0
- package/scripts/fix-payment-notifications.sql +41 -0
- package/scripts/force-new-round.js +55 -0
- package/scripts/force-resolve-and-claim.js +278 -0
- package/scripts/important/README.md +115 -0
- package/scripts/important/authority-force-lock.js +197 -0
- package/scripts/important/authority-resolve-game.js +267 -0
- package/scripts/important/check-game-status.js +373 -0
- package/scripts/important/list-pending-games-by-version.js +270 -0
- package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
- package/scripts/initialize-jackpot.js +111 -0
- package/scripts/jackpot/.claude/settings.local.json +10 -0
- package/scripts/jackpot/force-reset.js +84 -0
- package/scripts/jackpot/initialize-mainnet.js +100 -0
- package/scripts/jackpot/keeper.js +742 -0
- package/scripts/jackpot/status.js +107 -0
- package/scripts/jackpot/update-round-duration.js +143 -0
- package/scripts/keeper-bot.js +112 -0
- package/scripts/list-pending-games.js +131 -0
- package/scripts/migrate-chat-v2.js +127 -0
- package/scripts/migrate-chat-winners.js +84 -0
- package/scripts/migrate-chat.sh +17 -0
- package/scripts/migrate-game-invite.js +83 -0
- package/scripts/migrate-heroku-game-notifications.sh +159 -0
- package/scripts/migrations/001_analytics_tables.sql +422 -0
- package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
- package/scripts/migrations/003_referral_earnings.sql +208 -0
- package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
- package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
- package/scripts/migrations/005_push_notifications.sql +55 -0
- package/scripts/migrations/006_add_draw_team_players.sql +28 -0
- package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
- package/scripts/migrations/007_add_gif_url.sql +8 -0
- package/scripts/migrations/008_add_connect4_columns.sql +139 -0
- package/scripts/migrations/008_add_pool_tracking.sql +22 -0
- package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
- package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
- package/scripts/migrations/011_create_developer_tables.sql +67 -0
- package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
- package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
- package/scripts/migrations/013_add_network_mode.sql +18 -0
- package/scripts/migrations/014_create_developer_app_users.sql +19 -0
- package/scripts/migrations/015_add_ui_config.sql +4 -0
- package/scripts/migrations/016_add_resolution_secret.sql +4 -0
- package/scripts/migrations/017_add_external_game_id.sql +3 -0
- package/scripts/migrations/018_create_pickem_tables.sql +115 -0
- package/scripts/migrations/019_expo_push_tokens.sql +19 -0
- package/scripts/migrations/create_whats_new_tables.sql +88 -0
- package/scripts/migrations/drop_live_games_tables.sql +34 -0
- package/scripts/open-jackpot-round.js +85 -0
- package/scripts/purge-all-data.sh +329 -0
- package/scripts/purge-all-data.sql +142 -0
- package/scripts/purge-heroku-data.sh +149 -0
- package/scripts/purge-heroku-data.sql +62 -0
- package/scripts/rebuild-heroku-database.sh +113 -0
- package/scripts/recover-funds.js +357 -0
- package/scripts/regenerate-epl-images.js +278 -0
- package/scripts/resize-s3-matchup-images.js +374 -0
- package/scripts/resolve-direct.js +88 -0
- package/scripts/resolve-mock-game.js +124 -0
- package/scripts/resolve-pickem-game.js +55 -0
- package/scripts/resolve-round-manual.js +83 -0
- package/scripts/resolve-stuck-game.js +382 -0
- package/scripts/resolve-stuck-round.js +42 -0
- package/scripts/run-connect4-migration.sh +16 -0
- package/scripts/run-mention-migration.sh +32 -0
- package/scripts/run-payment-migration.sh +51 -0
- package/scripts/run-preferred-currency-migration.sh +31 -0
- package/scripts/run-referral-earnings-migration.sh +32 -0
- package/scripts/run-survivor-outcome-migration.sh +16 -0
- package/scripts/seed-test-users.js +346 -0
- package/scripts/setup-auth-tables.js +78 -0
- package/scripts/setup-complete-database.sql +992 -0
- package/scripts/setup-database-fresh.sh +359 -0
- package/scripts/setup-heroku-keeper.sh +48 -0
- package/scripts/setup-keeper-database.js +83 -0
- package/scripts/setup-keeper-state-db.sql +110 -0
- package/scripts/setup-oracle.sh +39 -0
- package/scripts/setup-pnl-tracking.js +111 -0
- package/scripts/start-devnet.sh +14 -0
- package/scripts/test-arcade-devnet.sh +160 -0
- package/scripts/test-arcade-match.sh +109 -0
- package/scripts/test-automatic-mode.sh +239 -0
- package/scripts/test-connect4-cancel-claim.js +370 -0
- package/scripts/test-connect4-e2e.js +369 -0
- package/scripts/test-connect4-resolve.js +369 -0
- package/scripts/test-game-state-endpoint.js +136 -0
- package/scripts/test-invite-notification.js +86 -0
- package/scripts/test-jackpot-api.sh +71 -0
- package/scripts/test-poll-confirmation.js +267 -0
- package/scripts/test-resolve-game.js +271 -0
- package/scripts/test-resolve-signature.js +223 -0
- package/scripts/test-signature-preservation.js +124 -0
- package/scripts/test-state-machine.js +291 -0
- package/scripts/test-webhook-receiver.js +60 -0
- package/scripts/update-notification-constraint.js +52 -0
- package/scripts/verify-account-layout.js +145 -0
- package/scripts/verify-winner-algorithm.js +278 -0
- package/server.js +5259 -0
- package/services/arcadeMatchService.js +763 -0
- package/services/automaticGameOracle.js +1596 -0
- package/services/chatService.js +1612 -0
- package/services/connect4GameService.js +1049 -0
- package/services/connect4NotificationService.js +374 -0
- package/services/cryptoPriceService.js +223 -0
- package/services/customGameResolver.js +260 -0
- package/services/db.js +79 -0
- package/services/directMessageService.js +389 -0
- package/services/discordNotifications.js +160 -0
- package/services/exchangeRateService.js +289 -0
- package/services/expoPushService.js +314 -0
- package/services/gamesCacheService.js +539 -0
- package/services/jackpotHistory.js +331 -0
- package/services/jackpotService.js +856 -0
- package/services/keeperStateService.js +355 -0
- package/services/matchupImageService.js +591 -0
- package/services/notificationCacheService.js +407 -0
- package/services/pickemOracle.js +440 -0
- package/services/playerStatsService.js +389 -0
- package/services/portfolioService.js +555 -0
- package/services/promoService.js +757 -0
- package/services/promoTreasuryService.js +239 -0
- package/services/pushNotifications.js +353 -0
- package/services/redisService.js +422 -0
- package/services/referralEarningsService.js +728 -0
- package/services/s3Service.js +396 -0
- package/services/socialService.js +1202 -0
- package/services/survivorOracle.js +469 -0
- package/services/survivorSimulator.js +475 -0
- package/services/telegramNotifications.js +461 -0
- package/services/userProfileStatsService.js +1185 -0
- package/services/whatsNewService.js +388 -0
- package/utils/urlHelper.js +95 -0
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Survivor Pool Routes
|
|
3
|
+
* API endpoints for March Madness Survivor Pool feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const express = require('express');
|
|
7
|
+
const router = express.Router();
|
|
8
|
+
const survivorController = require('../controllers/survivorController');
|
|
9
|
+
const { pool } = require('../services/db');
|
|
10
|
+
const { authenticate } = require('../middleware/authenticate');
|
|
11
|
+
|
|
12
|
+
// Socket.IO for real-time updates
|
|
13
|
+
let io = null;
|
|
14
|
+
|
|
15
|
+
// Inject Socket.IO instance
|
|
16
|
+
router.setSocketIO = (ioInstance) => {
|
|
17
|
+
io = ioInstance;
|
|
18
|
+
console.log('[Survivor] Socket.IO injected');
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// ============================================
|
|
22
|
+
// POOL MANAGEMENT
|
|
23
|
+
// ============================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* POST /api/survivor/pools
|
|
27
|
+
* Create a new survivor pool (admin only)
|
|
28
|
+
*/
|
|
29
|
+
router.post('/pools', async (req, res) => {
|
|
30
|
+
try {
|
|
31
|
+
const { name, year, buyInLamports, roundDeadline, allowSameTeamTwice, solanaGameId } = req.body;
|
|
32
|
+
|
|
33
|
+
// Get creator from auth header or body
|
|
34
|
+
const createdBy = req.body.createdBy || req.headers['x-wallet-address'];
|
|
35
|
+
|
|
36
|
+
if (!name || !year || !buyInLamports) {
|
|
37
|
+
return res.status(400).json({
|
|
38
|
+
success: false,
|
|
39
|
+
error: 'Missing required fields: name, year, buyInLamports'
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const pool = await survivorController.createPool({
|
|
44
|
+
name,
|
|
45
|
+
year,
|
|
46
|
+
buyInLamports,
|
|
47
|
+
roundDeadline,
|
|
48
|
+
allowSameTeamTwice,
|
|
49
|
+
solanaGameId,
|
|
50
|
+
createdBy
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
res.json({
|
|
54
|
+
success: true,
|
|
55
|
+
pool
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('[Survivor] Error creating pool:', error.message);
|
|
59
|
+
res.status(500).json({
|
|
60
|
+
success: false,
|
|
61
|
+
error: error.message
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* GET /api/survivor/pools
|
|
68
|
+
* List all survivor pools
|
|
69
|
+
*/
|
|
70
|
+
router.get('/pools', async (req, res) => {
|
|
71
|
+
try {
|
|
72
|
+
const { status, year } = req.query;
|
|
73
|
+
const pools = await survivorController.getPools({ status, year: year ? parseInt(year) : undefined });
|
|
74
|
+
|
|
75
|
+
res.json({
|
|
76
|
+
success: true,
|
|
77
|
+
pools
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('[Survivor] Error listing pools:', error.message);
|
|
81
|
+
res.status(500).json({
|
|
82
|
+
success: false,
|
|
83
|
+
error: error.message
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* GET /api/survivor/pools/:id
|
|
90
|
+
* Get pool details with leaderboard
|
|
91
|
+
*/
|
|
92
|
+
router.get('/pools/:id', async (req, res) => {
|
|
93
|
+
try {
|
|
94
|
+
const poolId = parseInt(req.params.id);
|
|
95
|
+
const survivorPool = await survivorController.getPoolById(poolId);
|
|
96
|
+
|
|
97
|
+
if (!survivorPool) {
|
|
98
|
+
return res.status(404).json({
|
|
99
|
+
success: false,
|
|
100
|
+
error: 'Pool not found'
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Get stats
|
|
105
|
+
const stats = await survivorController.getPoolStats(poolId);
|
|
106
|
+
|
|
107
|
+
// Get alive entries for leaderboard
|
|
108
|
+
const aliveEntries = await survivorController.getAliveEntries(poolId);
|
|
109
|
+
|
|
110
|
+
res.json({
|
|
111
|
+
success: true,
|
|
112
|
+
pool: survivorPool,
|
|
113
|
+
stats,
|
|
114
|
+
leaderboard: aliveEntries.slice(0, 20) // Top 20 for preview
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error('[Survivor] Error getting pool:', error.message);
|
|
118
|
+
res.status(500).json({
|
|
119
|
+
success: false,
|
|
120
|
+
error: error.message
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* PATCH /api/survivor/pools/:id
|
|
127
|
+
* Update pool settings (admin only)
|
|
128
|
+
*/
|
|
129
|
+
router.patch('/pools/:id', async (req, res) => {
|
|
130
|
+
try {
|
|
131
|
+
const poolId = parseInt(req.params.id);
|
|
132
|
+
const updates = req.body;
|
|
133
|
+
|
|
134
|
+
const updatedPool = await survivorController.updatePool(poolId, updates);
|
|
135
|
+
|
|
136
|
+
if (!updatedPool) {
|
|
137
|
+
return res.status(404).json({
|
|
138
|
+
success: false,
|
|
139
|
+
error: 'Pool not found'
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Emit update via Socket.IO if available
|
|
144
|
+
if (io) {
|
|
145
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
res.json({
|
|
149
|
+
success: true,
|
|
150
|
+
pool: updatedPool
|
|
151
|
+
});
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error('[Survivor] Error updating pool:', error.message);
|
|
154
|
+
res.status(500).json({
|
|
155
|
+
success: false,
|
|
156
|
+
error: error.message
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ============================================
|
|
162
|
+
// ENTRY MANAGEMENT
|
|
163
|
+
// ============================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* POST /api/survivor/pools/:id/join
|
|
167
|
+
* Join a survivor pool
|
|
168
|
+
*/
|
|
169
|
+
router.post('/pools/:id/join', authenticate, async (req, res) => {
|
|
170
|
+
try {
|
|
171
|
+
const poolId = parseInt(req.params.id);
|
|
172
|
+
const { userId, walletAddress } = req.user;
|
|
173
|
+
const { txSignature } = req.body;
|
|
174
|
+
|
|
175
|
+
const entry = await survivorController.joinPool({
|
|
176
|
+
poolId,
|
|
177
|
+
userId,
|
|
178
|
+
walletAddress,
|
|
179
|
+
txSignature
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Emit join event via Socket.IO
|
|
183
|
+
if (io) {
|
|
184
|
+
io.emit('survivor:entry_joined', { poolId, entry });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
res.json({
|
|
188
|
+
success: true,
|
|
189
|
+
entry
|
|
190
|
+
});
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('[Survivor] Error joining pool:', error.message);
|
|
193
|
+
res.status(400).json({
|
|
194
|
+
success: false,
|
|
195
|
+
error: error.message
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* GET /api/survivor/pools/:id/my-entry
|
|
202
|
+
* Get current user's entry and picks
|
|
203
|
+
*/
|
|
204
|
+
router.get('/pools/:id/my-entry', authenticate, async (req, res) => {
|
|
205
|
+
try {
|
|
206
|
+
const poolId = parseInt(req.params.id);
|
|
207
|
+
const { userId } = req.user;
|
|
208
|
+
|
|
209
|
+
const entryWithPicks = await survivorController.getUserEntry(poolId, userId);
|
|
210
|
+
|
|
211
|
+
if (!entryWithPicks) {
|
|
212
|
+
return res.status(404).json({
|
|
213
|
+
success: false,
|
|
214
|
+
error: 'Entry not found - user has not joined this pool'
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Get pool info too
|
|
219
|
+
const survivorPool = await survivorController.getPoolById(poolId);
|
|
220
|
+
|
|
221
|
+
// Extract picks from entry and format response
|
|
222
|
+
const { picks, ...entry } = entryWithPicks;
|
|
223
|
+
|
|
224
|
+
res.json({
|
|
225
|
+
success: true,
|
|
226
|
+
entry,
|
|
227
|
+
picks: picks || [],
|
|
228
|
+
pool: survivorPool
|
|
229
|
+
});
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error('[Survivor] Error getting user entry:', error.message);
|
|
232
|
+
res.status(500).json({
|
|
233
|
+
success: false,
|
|
234
|
+
error: error.message
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// ============================================
|
|
240
|
+
// PICKS
|
|
241
|
+
// ============================================
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* GET /api/survivor/pools/:id/teams
|
|
245
|
+
* Get available teams for current round
|
|
246
|
+
*/
|
|
247
|
+
router.get('/pools/:id/teams', authenticate, async (req, res) => {
|
|
248
|
+
try {
|
|
249
|
+
const poolId = parseInt(req.params.id);
|
|
250
|
+
const { userId } = req.user;
|
|
251
|
+
|
|
252
|
+
const teamsData = await survivorController.getAvailableTeams(poolId, userId);
|
|
253
|
+
|
|
254
|
+
res.json({
|
|
255
|
+
success: true,
|
|
256
|
+
...teamsData
|
|
257
|
+
});
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.error('[Survivor] Error getting teams:', error.message);
|
|
260
|
+
res.status(400).json({
|
|
261
|
+
success: false,
|
|
262
|
+
error: error.message
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* POST /api/survivor/pools/:id/pick
|
|
269
|
+
* Submit pick for current round
|
|
270
|
+
*/
|
|
271
|
+
router.post('/pools/:id/pick', authenticate, async (req, res) => {
|
|
272
|
+
try {
|
|
273
|
+
const poolId = parseInt(req.params.id);
|
|
274
|
+
const { userId } = req.user;
|
|
275
|
+
const { teamId, teamName, teamSeed, teamLogo, espnGameId, opponentName, opponentSeed } = req.body;
|
|
276
|
+
|
|
277
|
+
if (!teamId || !teamName) {
|
|
278
|
+
return res.status(400).json({
|
|
279
|
+
success: false,
|
|
280
|
+
error: 'Missing required fields: teamId, teamName'
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const pick = await survivorController.submitPick({
|
|
285
|
+
poolId,
|
|
286
|
+
userId,
|
|
287
|
+
teamId,
|
|
288
|
+
teamName,
|
|
289
|
+
teamSeed,
|
|
290
|
+
teamLogo,
|
|
291
|
+
espnGameId,
|
|
292
|
+
opponentName,
|
|
293
|
+
opponentSeed
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Emit pick event via Socket.IO
|
|
297
|
+
if (io) {
|
|
298
|
+
io.emit('survivor:pick_submitted', { poolId, userId, pick });
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
res.json({
|
|
302
|
+
success: true,
|
|
303
|
+
pick
|
|
304
|
+
});
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error('[Survivor] Error submitting pick:', error.message);
|
|
307
|
+
res.status(400).json({
|
|
308
|
+
success: false,
|
|
309
|
+
error: error.message
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* GET /api/survivor/pools/:id/picks
|
|
316
|
+
* Get all picks for user
|
|
317
|
+
*/
|
|
318
|
+
router.get('/pools/:id/picks', authenticate, async (req, res) => {
|
|
319
|
+
try {
|
|
320
|
+
const poolId = parseInt(req.params.id);
|
|
321
|
+
const { userId } = req.user;
|
|
322
|
+
|
|
323
|
+
const picks = await survivorController.getUserPicks(poolId, userId);
|
|
324
|
+
|
|
325
|
+
res.json({
|
|
326
|
+
success: true,
|
|
327
|
+
picks
|
|
328
|
+
});
|
|
329
|
+
} catch (error) {
|
|
330
|
+
console.error('[Survivor] Error getting picks:', error.message);
|
|
331
|
+
res.status(500).json({
|
|
332
|
+
success: false,
|
|
333
|
+
error: error.message
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// ============================================
|
|
339
|
+
// LEADERBOARD
|
|
340
|
+
// ============================================
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* GET /api/survivor/pools/:id/alive
|
|
344
|
+
* Get surviving entries
|
|
345
|
+
*/
|
|
346
|
+
router.get('/pools/:id/alive', async (req, res) => {
|
|
347
|
+
try {
|
|
348
|
+
const poolId = parseInt(req.params.id);
|
|
349
|
+
const entries = await survivorController.getAliveEntries(poolId);
|
|
350
|
+
|
|
351
|
+
res.json({
|
|
352
|
+
success: true,
|
|
353
|
+
count: entries.length,
|
|
354
|
+
entries
|
|
355
|
+
});
|
|
356
|
+
} catch (error) {
|
|
357
|
+
console.error('[Survivor] Error getting alive entries:', error.message);
|
|
358
|
+
res.status(500).json({
|
|
359
|
+
success: false,
|
|
360
|
+
error: error.message
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* GET /api/survivor/pools/:id/eliminated
|
|
367
|
+
* Get eliminated entries
|
|
368
|
+
*/
|
|
369
|
+
router.get('/pools/:id/eliminated', async (req, res) => {
|
|
370
|
+
try {
|
|
371
|
+
const poolId = parseInt(req.params.id);
|
|
372
|
+
const entries = await survivorController.getEliminatedEntries(poolId);
|
|
373
|
+
|
|
374
|
+
res.json({
|
|
375
|
+
success: true,
|
|
376
|
+
count: entries.length,
|
|
377
|
+
entries
|
|
378
|
+
});
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.error('[Survivor] Error getting eliminated entries:', error.message);
|
|
381
|
+
res.status(500).json({
|
|
382
|
+
success: false,
|
|
383
|
+
error: error.message
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* GET /api/survivor/pools/:id/stats
|
|
390
|
+
* Get pool statistics
|
|
391
|
+
*/
|
|
392
|
+
router.get('/pools/:id/stats', async (req, res) => {
|
|
393
|
+
try {
|
|
394
|
+
const poolId = parseInt(req.params.id);
|
|
395
|
+
const stats = await survivorController.getPoolStats(poolId);
|
|
396
|
+
|
|
397
|
+
res.json({
|
|
398
|
+
success: true,
|
|
399
|
+
stats
|
|
400
|
+
});
|
|
401
|
+
} catch (error) {
|
|
402
|
+
console.error('[Survivor] Error getting stats:', error.message);
|
|
403
|
+
res.status(500).json({
|
|
404
|
+
success: false,
|
|
405
|
+
error: error.message
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// ============================================
|
|
411
|
+
// ADMIN / ORACLE ENDPOINTS
|
|
412
|
+
// ============================================
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* POST /api/survivor/pools/:id/games
|
|
416
|
+
* Import tournament games (admin)
|
|
417
|
+
*/
|
|
418
|
+
router.post('/pools/:id/games', async (req, res) => {
|
|
419
|
+
try {
|
|
420
|
+
const poolId = parseInt(req.params.id);
|
|
421
|
+
const { games } = req.body;
|
|
422
|
+
|
|
423
|
+
if (!games || !Array.isArray(games)) {
|
|
424
|
+
return res.status(400).json({
|
|
425
|
+
success: false,
|
|
426
|
+
error: 'Missing required field: games (array)'
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const importedGames = await survivorController.importTournamentGames(poolId, games);
|
|
431
|
+
|
|
432
|
+
res.json({
|
|
433
|
+
success: true,
|
|
434
|
+
count: importedGames.length,
|
|
435
|
+
games: importedGames
|
|
436
|
+
});
|
|
437
|
+
} catch (error) {
|
|
438
|
+
console.error('[Survivor] Error importing games:', error.message);
|
|
439
|
+
res.status(500).json({
|
|
440
|
+
success: false,
|
|
441
|
+
error: error.message
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* GET /api/survivor/pools/:id/games
|
|
448
|
+
* Get tournament games for a pool
|
|
449
|
+
*/
|
|
450
|
+
router.get('/pools/:id/games', async (req, res) => {
|
|
451
|
+
try {
|
|
452
|
+
const poolId = parseInt(req.params.id);
|
|
453
|
+
const { round } = req.query;
|
|
454
|
+
|
|
455
|
+
console.log(`[Survivor] GET /games - poolId: ${poolId}, round: ${round || 'all'}`);
|
|
456
|
+
|
|
457
|
+
let query = 'SELECT * FROM survivor_tournament_games WHERE pool_id = $1';
|
|
458
|
+
const params = [poolId];
|
|
459
|
+
|
|
460
|
+
if (round) {
|
|
461
|
+
params.push(parseInt(round));
|
|
462
|
+
query += ` AND round = $${params.length}`;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
query += ' ORDER BY round, game_date, id';
|
|
466
|
+
|
|
467
|
+
const result = await pool.query(query, params);
|
|
468
|
+
|
|
469
|
+
console.log(`[Survivor] GET /games - found ${result.rows.length} games`);
|
|
470
|
+
|
|
471
|
+
res.json({
|
|
472
|
+
success: true,
|
|
473
|
+
count: result.rows.length,
|
|
474
|
+
games: result.rows
|
|
475
|
+
});
|
|
476
|
+
} catch (error) {
|
|
477
|
+
console.error('[Survivor] Error getting games:', error.message);
|
|
478
|
+
res.status(500).json({
|
|
479
|
+
success: false,
|
|
480
|
+
error: error.message
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* POST /api/survivor/pools/:id/resolve
|
|
487
|
+
* Resolve current round (oracle)
|
|
488
|
+
* Called by survivorOracle service after games complete
|
|
489
|
+
*/
|
|
490
|
+
router.post('/pools/:id/resolve', async (req, res) => {
|
|
491
|
+
try {
|
|
492
|
+
const poolId = parseInt(req.params.id);
|
|
493
|
+
|
|
494
|
+
// This endpoint is called by the oracle service
|
|
495
|
+
// Import the oracle and trigger resolution
|
|
496
|
+
const survivorOracle = require('../services/survivorOracle');
|
|
497
|
+
const result = await survivorOracle.resolveCurrentRound(poolId);
|
|
498
|
+
|
|
499
|
+
// Emit round resolved event
|
|
500
|
+
if (io) {
|
|
501
|
+
io.emit('survivor:round_resolved', { poolId, result });
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
res.json({
|
|
505
|
+
success: true,
|
|
506
|
+
result
|
|
507
|
+
});
|
|
508
|
+
} catch (error) {
|
|
509
|
+
console.error('[Survivor] Error resolving round:', error.message);
|
|
510
|
+
res.status(500).json({
|
|
511
|
+
success: false,
|
|
512
|
+
error: error.message
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// ============================================
|
|
518
|
+
// DEV / SIMULATION ENDPOINTS (development only)
|
|
519
|
+
// ============================================
|
|
520
|
+
|
|
521
|
+
// Only enable in development
|
|
522
|
+
if (process.env.NODE_ENV === 'development' || process.env.ENABLE_SURVIVOR_DEV === 'true') {
|
|
523
|
+
const survivorSimulator = require('../services/survivorSimulator');
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* POST /api/survivor/dev/pools/:id/generate-bracket
|
|
527
|
+
* Generate mock tournament bracket for testing
|
|
528
|
+
*/
|
|
529
|
+
router.post('/dev/pools/:id/generate-bracket', async (req, res) => {
|
|
530
|
+
try {
|
|
531
|
+
const poolId = parseInt(req.params.id);
|
|
532
|
+
const games = await survivorSimulator.generateTournamentBracket(poolId);
|
|
533
|
+
|
|
534
|
+
// Emit pool updated for real-time bracket refresh
|
|
535
|
+
if (io) {
|
|
536
|
+
const updatedPool = await survivorController.getPoolById(poolId);
|
|
537
|
+
if (updatedPool) {
|
|
538
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
res.json({
|
|
543
|
+
success: true,
|
|
544
|
+
message: `Generated ${games.length} tournament games`,
|
|
545
|
+
count: games.length
|
|
546
|
+
});
|
|
547
|
+
} catch (error) {
|
|
548
|
+
console.error('[Survivor:Dev] Error generating bracket:', error.message);
|
|
549
|
+
res.status(500).json({
|
|
550
|
+
success: false,
|
|
551
|
+
error: error.message
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* POST /api/survivor/dev/pools/:id/simulate-round
|
|
558
|
+
* Simulate current round with random results
|
|
559
|
+
*/
|
|
560
|
+
router.post('/dev/pools/:id/simulate-round', async (req, res) => {
|
|
561
|
+
try {
|
|
562
|
+
const poolId = parseInt(req.params.id);
|
|
563
|
+
const { upsetChance = 0.2, favorChalk = false } = req.body;
|
|
564
|
+
|
|
565
|
+
const result = await survivorSimulator.simulateRound(poolId, { upsetChance, favorChalk });
|
|
566
|
+
|
|
567
|
+
// Emit round resolved event for real-time updates
|
|
568
|
+
if (io && result.resolution) {
|
|
569
|
+
io.emit('survivor:round_resolved', { poolId, result: result.resolution });
|
|
570
|
+
|
|
571
|
+
// Also emit pool updated with latest pool state
|
|
572
|
+
const updatedPool = await survivorController.getPoolById(poolId);
|
|
573
|
+
if (updatedPool) {
|
|
574
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
res.json({
|
|
579
|
+
success: true,
|
|
580
|
+
result
|
|
581
|
+
});
|
|
582
|
+
} catch (error) {
|
|
583
|
+
console.error('[Survivor:Dev] Error simulating round:', error.message);
|
|
584
|
+
res.status(500).json({
|
|
585
|
+
success: false,
|
|
586
|
+
error: error.message
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* POST /api/survivor/dev/pools/:id/generate-entries
|
|
593
|
+
* Generate test entries with random picks
|
|
594
|
+
*/
|
|
595
|
+
router.post('/dev/pools/:id/generate-entries', async (req, res) => {
|
|
596
|
+
try {
|
|
597
|
+
const poolId = parseInt(req.params.id);
|
|
598
|
+
const { count = 10 } = req.body;
|
|
599
|
+
|
|
600
|
+
const result = await survivorSimulator.generateTestEntries(poolId, count);
|
|
601
|
+
|
|
602
|
+
res.json({
|
|
603
|
+
success: true,
|
|
604
|
+
result
|
|
605
|
+
});
|
|
606
|
+
} catch (error) {
|
|
607
|
+
console.error('[Survivor:Dev] Error generating entries:', error.message);
|
|
608
|
+
res.status(500).json({
|
|
609
|
+
success: false,
|
|
610
|
+
error: error.message
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* POST /api/survivor/dev/pools/:id/set-deadline
|
|
617
|
+
* Set round deadline to N minutes from now
|
|
618
|
+
*/
|
|
619
|
+
router.post('/dev/pools/:id/set-deadline', async (req, res) => {
|
|
620
|
+
try {
|
|
621
|
+
const poolId = parseInt(req.params.id);
|
|
622
|
+
const { minutes = 5 } = req.body;
|
|
623
|
+
|
|
624
|
+
const result = await survivorSimulator.setDeadline(poolId, minutes);
|
|
625
|
+
|
|
626
|
+
// Emit pool updated for real-time refresh
|
|
627
|
+
if (io) {
|
|
628
|
+
const updatedPool = await survivorController.getPoolById(poolId);
|
|
629
|
+
if (updatedPool) {
|
|
630
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
res.json({
|
|
635
|
+
success: true,
|
|
636
|
+
result
|
|
637
|
+
});
|
|
638
|
+
} catch (error) {
|
|
639
|
+
console.error('[Survivor:Dev] Error setting deadline:', error.message);
|
|
640
|
+
res.status(500).json({
|
|
641
|
+
success: false,
|
|
642
|
+
error: error.message
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* POST /api/survivor/dev/pools/:id/reset
|
|
649
|
+
* Reset pool to round 1
|
|
650
|
+
* Body: { deleteEntries: boolean } - if true, also delete all entries
|
|
651
|
+
*/
|
|
652
|
+
router.post('/dev/pools/:id/reset', async (req, res) => {
|
|
653
|
+
try {
|
|
654
|
+
const poolId = parseInt(req.params.id);
|
|
655
|
+
const { deleteEntries = false } = req.body;
|
|
656
|
+
|
|
657
|
+
const result = await survivorSimulator.resetPool(poolId, { deleteEntries });
|
|
658
|
+
|
|
659
|
+
// Emit pool updated for real-time refresh
|
|
660
|
+
if (io) {
|
|
661
|
+
const updatedPool = await survivorController.getPoolById(poolId);
|
|
662
|
+
if (updatedPool) {
|
|
663
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
res.json({
|
|
668
|
+
success: true,
|
|
669
|
+
result
|
|
670
|
+
});
|
|
671
|
+
} catch (error) {
|
|
672
|
+
console.error('[Survivor:Dev] Error resetting pool:', error.message);
|
|
673
|
+
res.status(500).json({
|
|
674
|
+
success: false,
|
|
675
|
+
error: error.message
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* POST /api/survivor/dev/pools/:id/activate
|
|
682
|
+
* Activate pool and set to round 2
|
|
683
|
+
*/
|
|
684
|
+
router.post('/dev/pools/:id/activate', async (req, res) => {
|
|
685
|
+
try {
|
|
686
|
+
const poolId = parseInt(req.params.id);
|
|
687
|
+
const result = await survivorSimulator.activatePool(poolId);
|
|
688
|
+
|
|
689
|
+
// Emit pool updated for real-time refresh
|
|
690
|
+
if (io) {
|
|
691
|
+
const updatedPool = await survivorController.getPoolById(poolId);
|
|
692
|
+
if (updatedPool) {
|
|
693
|
+
io.emit('survivor:pool_updated', { poolId, pool: updatedPool });
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
res.json({
|
|
698
|
+
success: true,
|
|
699
|
+
result
|
|
700
|
+
});
|
|
701
|
+
} catch (error) {
|
|
702
|
+
console.error('[Survivor:Dev] Error activating pool:', error.message);
|
|
703
|
+
res.status(500).json({
|
|
704
|
+
success: false,
|
|
705
|
+
error: error.message
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* DELETE /api/survivor/dev/pools/:id/test-entries
|
|
712
|
+
* Delete test entries (cleanup)
|
|
713
|
+
*/
|
|
714
|
+
router.delete('/dev/pools/:id/test-entries', async (req, res) => {
|
|
715
|
+
try {
|
|
716
|
+
const poolId = parseInt(req.params.id);
|
|
717
|
+
const result = await survivorSimulator.deleteTestEntries(poolId);
|
|
718
|
+
|
|
719
|
+
res.json({
|
|
720
|
+
success: true,
|
|
721
|
+
result
|
|
722
|
+
});
|
|
723
|
+
} catch (error) {
|
|
724
|
+
console.error('[Survivor:Dev] Error deleting test entries:', error.message);
|
|
725
|
+
res.status(500).json({
|
|
726
|
+
success: false,
|
|
727
|
+
error: error.message
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* GET /api/survivor/dev/teams
|
|
734
|
+
* Get list of mock tournament teams
|
|
735
|
+
*/
|
|
736
|
+
router.get('/dev/teams', async (req, res) => {
|
|
737
|
+
try {
|
|
738
|
+
const { MOCK_TEAMS } = require('../services/survivorSimulator');
|
|
739
|
+
res.json({
|
|
740
|
+
success: true,
|
|
741
|
+
count: MOCK_TEAMS.length,
|
|
742
|
+
teams: MOCK_TEAMS
|
|
743
|
+
});
|
|
744
|
+
} catch (error) {
|
|
745
|
+
console.error('[Survivor:Dev] Error getting teams:', error.message);
|
|
746
|
+
res.status(500).json({
|
|
747
|
+
success: false,
|
|
748
|
+
error: error.message
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
console.log('[Survivor] Dev/simulation endpoints enabled');
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
module.exports = router;
|