const express = require('express'); const { requireAuth } = require('../middleware/auth'); const { checkGracePeriod } = require('../middleware/gracePeriod'); const { getSupabaseServiceClient } = require('../utils/supabase'); const router = express.Router(); // GET /joint-history — joint outcome history and phi coefficient router.get('/joint-history', requireAuth, checkGracePeriod, async (req, res) => { const { player_a, stat_a, player_b, stat_b } = req.query; // Block free tier if (!req.user.tier || req.user.tier === 'free') { return res.status(403).json({ error: 'Joint history requires Analyst or Desk tier', upgrade_url: '/pricing', }); } if (!player_a || !stat_a || !player_b || !stat_b) { return res.status(400).json({ error: 'Required query params: player_a, stat_a, player_b, stat_b', }); } try { const supabase = getSupabaseServiceClient(); const { data, error } = await supabase .from('joint_outcomes') .select('*') .eq('player_a', player_a) .eq('stat_a', stat_a) .eq('player_b', player_b) .eq('stat_b', stat_b); if (error) throw error; if (!data || data.length === 0) { return res.json({ player_a, stat_a, player_b, stat_b, sample_size: 0, phi_coefficient: null, outcomes: [], }); } // Calculate phi coefficient from joint outcomes let both_hit = 0, a_only = 0, b_only = 0, neither = 0; for (const row of data) { if (row.a_hit && row.b_hit) both_hit++; else if (row.a_hit && !row.b_hit) a_only++; else if (!row.a_hit && row.b_hit) b_only++; else neither++; } const n = data.length; const num = (both_hit * neither) - (a_only * b_only); const denom = Math.sqrt( (both_hit + a_only) * (b_only + neither) * (both_hit + b_only) * (a_only + neither) ); const phi = denom === 0 ? 0 : num / denom; res.json({ player_a, stat_a, player_b, stat_b, sample_size: n, phi_coefficient: Math.round(phi * 1000) / 1000, outcomes: data, }); } catch (err) { console.error('[props/joint-history]', err.message); res.status(503).json({ error: 'Service temporarily unavailable' }); } }); module.exports = router;