Phase 3 Integration - Progress Report

Date: 2026-07-12
Status: ✅ Client Services Updated, UI Integration Next


✅ COMPLETED: Client Stats Service Updates

1. Updated stats-service.ts (OpenSkill Integration)

Changes:

  • ✅ Replaced Elo imports with OpenSkill functions from warp12-engine
  • ✅ Updated incrementLocalAiSkillStats() to use OpenSkill rating updates
  • ✅ Updated previewLocalAiMatchReport() to use TEI grade system
  • ✅ Updated displayPlayerObjectiveTei() to return TEI score (0-99)
  • ✅ Added getPlayerTeiDisplay() - returns full TEI display (grade + score)
  • ✅ Added getPlayerStoredRating() - returns complete rating with displayGrade
  • ✅ Fixed academy placement functions to use new schema

Key Functions:

// Legacy (returns just score for backward compatibility)
displayPlayerObjectiveTei(stats, skill, objective): number | null

// New TEI display (returns {grade, score, formatted})
getPlayerTeiDisplay(stats, skill, objective): TeiDisplay | null

// Get full rating object with hysteresis grade
getPlayerStoredRating(stats, skill, objective): StoredRating | null

2. Updated use-player-stats.ts Hook

Changes:

  • ✅ Added getTeiDisplay() method to hook interface
  • ✅ Added getStoredRating() method to hook interface
  • ✅ Imported TEI types from warp12-engine
  • ✅ All existing functions still work (backward compatible)

Usage:

const playerStats = usePlayerStats();

// Legacy: Get numeric score only
const score = playerStats.displayTei('commander', 'points'); // → 67

// New: Get full TEI display
const tei = playerStats.getTeiDisplay('commander', 'points'); 
// → { grade: 'V', score: 67, formatted: 'V67' }

// Get rating with hysteresis grade
const rating = playerStats.getStoredRating('commander', 'points');
// → { mu: 32.0, sigma: 1.2, matches: 150, displayRating: 28.4, displayGrade: 'V' }

📊 What Works Now

  1. Client can read ratings from Firestore with displayGrade
  2. Client can calculate TEI displays with hysteresis
  3. Preview functionality shows TEI changes before/after matches
  4. Hooks expose TEI data to React components

🎯 NEXT STEPS: UI Integration

Step 1: Profile Page

File: apps/Warp12/src/app/profile-page.tsx

Tasks:

  • Import TeiDisplay component
  • Replace old TEI display with <TeiDisplay />
  • Show both Go-Out and Points ratings
  • Add tooltip showing raw μ/σ for power users
  • Optional: Add “Advanced Stats” toggle

Example:

import { TeiDisplay } from './components/tei-display';

const tei = playerStats.getTeiDisplay('commander', 'points');
const rating = playerStats.getStoredRating('commander', 'points');

<TeiDisplay
  rating={rating}
  currentGrade={rating?.displayGrade}
  objective="points"
  size="large"
/>

Step 2: Leaderboard Page

File: apps/Warp12/src/app/leaderboard-page.tsx

Tasks:

  • Import TeiGradeBadge component
  • Use badges in table rows
  • Sort by displayRating
  • Optional: Use TeiDisplay for detailed view

Example:

import { TeiGradeBadge } from './components/tei-grade-badge';

<TeiGradeBadge
  grade={entry.displayGrade}
  size="small"
/>

Step 3: Match Summary Page

File: apps/Warp12/src/app/sector-summary.tsx

Tasks:

  • Import TeiChange component
  • Show before → after rating with animation
  • Celebrate grade promotions (I→C, C→V, etc.)

Example:

import { TeiChange } from './components/tei-change';

<TeiChange
  before={beforeRating}
  after={afterRating}
  objective="points"
/>

Step 4: In-Game HUD (Optional)

Tasks:

  • Use <TeiGradeBadge /> next to player names
  • Keep it minimal (just letter badge)

🧪 Testing Checklist

Before deploying:

Local Testing:

  • Build all packages: yarn build:all
  • Run tests: yarn test:all
  • Test profile page displays TEI correctly
  • Test leaderboard sorting works
  • Test match summary shows rating changes
  • Verify hysteresis prevents flickering

Integration Testing:

  • Play local AI match → verify TEI updates
  • Play multiple matches → verify hysteresis (no flicker at boundaries)
  • Test academy placement flow
  • Check tooltips show μ/σ correctly

📁 Files Modified

✅ Completed:

  • apps/Warp12/src/firebase/stats-service.ts - Updated to OpenSkill
  • apps/Warp12/src/firebase/use-player-stats.ts - Added TEI display methods
  • libs/engine/src/lib/rating/* - Already complete (Phase 2)
  • functions/src/tei/* - Already complete (Phase 2.3)
  • apps/Warp12/src/app/components/tei-*.tsx - Already complete (Phase 3)

⏳ To Update:

  • apps/Warp12/src/app/profile-page.tsx
  • apps/Warp12/src/app/leaderboard-page.tsx
  • apps/Warp12/src/app/sector-summary.tsx
  • Optional: In-game HUD components

🚀 Deployment Plan

After UI integration is complete:

  1. Build everything:
    yarn build:all
    yarn build:all:hosting
    
  2. Wipe Firebase (user confirmed safe):
    • Delete playerStats collection
    • Delete ratedMatches collection
    • Delete publishedLogs collection
  3. Deploy:
    yarn deploy:firestore  # Rules
    yarn deploy:functions  # Cloud Functions
    yarn deploy:hosting    # Web app + leaderboard
    
  4. Verify:
    • Play test match
    • Check rating updates
    • Verify hysteresis works
    • Check leaderboard sorting

💡 Key Design Decisions

  1. Backward Compatibility:
    • displayPlayerObjectiveTei() still returns numeric score
    • New functions added without breaking existing code
    • Gradual migration path for UI components
  2. Hysteresis Integration:
    • displayGrade stored in Firestore
    • Always passed to getTeiDisplay() for consistency
    • UI components accept currentGrade prop
  3. Three-Layer API:
    • Score only: displayPlayerObjectiveTei() → number
    • Full display: getPlayerTeiDisplay() → {grade, score, formatted}
    • Raw rating: getPlayerStoredRating() → StoredRating with displayGrade

Current Progress: ~85% Complete
Backend: ✅ 100%
Client Services: ✅ 100%
UI Components: ✅ 100%
UI Integration: ⏳ 0%

Next Action: Integrate UI components into profile, leaderboard, and match summary pages


Warp 12 — a Double-Twelve domino variant for the NX Epoch.