NBA Game Simulator Design Document

Overview

An interactive single-page NBA game simulator integrated into the Jekyll blog. Users select two NBA teams, run a simulation based on real team statistics, and view realistic game results including quarter scores, final score, and MVP highlights.

Goals

  • Provide an engaging, fun NBA game simulation experience
  • Use real team statistics for realistic outcomes
  • Integrate seamlessly with the existing blog design
  • Work entirely client-side with no backend required

Competitive Analysis

Existing NBA Simulators

Product Type Pros Cons
MyGameSim Web app Play-by-play simulation, player projections, injury reports Ads, premium features behind $6.67/mo paywall, cluttered UI
Basketball GM Browser game Full franchise management, historical rosters, 100% free Not a quick game simulator—requires long-term commitment
WhatIfSports SimLeague Fantasy sim Build teams from NBA history, league play Complex setup, focused on season-long fantasy
FiveThirtyEight RAPTOR Predictions Advanced player-level metrics, high accuracy Read-only predictions, no interactive simulation
ESPN BPI Predictions Official NBA integration, real-time updates No interactive simulation, just win probabilities

Gap Analysis

What existing products lack:

  1. Simplicity - Most simulators are bloated with features. MyGameSim has ads, paywalls, and complex UI. Basketball GM requires hours of gameplay.

  2. Blog integration - No simulator is designed to be embedded in a personal blog or portfolio.

  3. Transparency - Proprietary algorithms (RAPTOR, BPI) don’t show their work. Users can’t understand why Team A beats Team B.

  4. Speed - Most require account creation, have slow load times, or require multiple clicks to simulate.

Our Differentiation

Competitor Gap Our Solution
Complex UI with ads Clean, minimal interface with zero ads
Account required No login, works instantly
Opaque algorithms Open-source, documented simulation logic
Standalone product Integrated into blog, shareable results
Premium features locked 100% free, all features available
Heavy JavaScript frameworks Vanilla JS, loads in < 1 second

Target Use Cases

Unlike MyGameSim (serious bettors) or Basketball GM (franchise sim enthusiasts), we target:

  • Casual fans who want quick “what if” matchups
  • Blog readers looking for interactive content
  • Developers who want to learn simulation algorithms
  • Social sharers who want to debate game predictions

Architecture

┌─────────────────────────────────────────────────────────────┐
│                     User Interface                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │Team Selection│  │Simulate Btn │  │   Game Results      │ │
│  └─────────────┘  └─────────────┘  └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                   Simulation Engine                         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │ Team Stats  │──│Monte Carlo  │──│  Quarter Scoring    │ │
│  │             │  │  Algorithm  │  │                     │ │
│  └─────────────┘  └─────────────┘  └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────┐
│                      Data Layer                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │
│  │balldontlie  │  │ localStorage│  │  Static JSON        │ │
│  │    API      │  │   Cache     │  │    Fallback         │ │
│  └─────────────┘  └─────────────┘  └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Data Strategy

Primary: balldontlie API

The balldontlie API provides free NBA statistics:

Free Tier Includes:

  • All 30 NBA teams
  • Current season games and stats
  • Player data and season averages

Limitations:

  • Free tier: current season only
  • Rate limits apply
  • Historical data requires paid tier

Caching Strategy

// Cache structure
{
  "teams": [...],
  "lastUpdated": "2026-01-26T10:00:00Z",
  "expiresAt": "2026-01-27T10:00:00Z"  // 24-hour TTL
}
  • Store fetched data in localStorage
  • 24-hour cache expiration
  • Reduces API calls and improves performance

Fallback: Static JSON

Include _data/nba-teams.json with all 30 teams:

{
  "teams": [
    {
      "id": 1,
      "name": "Hawks",
      "city": "Atlanta",
      "abbreviation": "ATL",
      "conference": "East",
      "division": "Southeast",
      "primaryColor": "#E03A3E",
      "secondaryColor": "#C1D32F",
      "stats": {
        "ppg": 118.2,
        "oppg": 120.5,
        "pace": 101.2,
        "winPct": 0.415
      }
    }
    // ... 29 more teams
  ]
}

Simulation Algorithm

Possession-Based Model

The simulation uses a possession-based approach that mirrors real NBA gameplay:

function simulateGame(homeTeam, awayTeam) {
    // 1. Calculate expected possessions
    const avgPace = (homeTeam.pace + awayTeam.pace) / 2;
    const possessionsPerQuarter = avgPace / 4;
    
    // 2. Calculate scoring efficiency
    // Offensive rating vs opponent's defensive rating
    const homeOffEff = homeTeam.ppg / 100;
    const awayDefEff = awayTeam.oppg / 100;
    const homeExpectedPPP = (homeOffEff + (100 - awayDefEff)) / 2;
    
    // 3. Simulate each quarter
    for (let q = 1; q <= 4; q++) {
        quarterScore = simulateQuarter(possessionsPerQuarter, homeExpectedPPP);
    }
    
    // 4. Handle overtime if tied
    while (homeScore === awayScore) {
        simulateOvertime();
    }
    
    return gameResult;
}

Key Factors

Factor Impact Implementation
Offensive Rating (PPG) Determines scoring probability Higher PPG = more points per possession
Defensive Rating (OPPG) Reduces opponent scoring Lower OPPG = better defense
Pace Number of possessions Fast pace = more scoring opportunities
Home Court Advantage +3-4 points for home team Applied as bonus to home scoring
Win Percentage Momentum/clutch factor Affects close-game outcomes
Quarter Variance Realistic scoring fluctuation Random variance per quarter

Randomness and Realism

// Add controlled randomness for realistic variance
function addVariance(expectedScore, variance = 0.15) {
    const factor = 1 + (Math.random() - 0.5) * variance;
    return Math.round(expectedScore * factor);
}

File Structure

github-blog/
├── nba-simulator.md              # Main simulator page
├── assets/
│   └── js/
│       └── nba-simulator.js      # Simulation engine + API
└── _data/
    └── nba-teams.json            # Static fallback data (30 teams)

User Interface Design

Team Selection

┌────────────────────────────────────────────────────────┐
│                  NBA GAME SIMULATOR                    │
├────────────────────────────────────────────────────────┤
│                                                        │
│   HOME TEAM              vs           AWAY TEAM        │
│  ┌──────────────┐              ┌──────────────┐       │
│  │ [Lakers  ▼] │              │ [Celtics ▼] │       │
│  └──────────────┘              └──────────────┘       │
│                                                        │
│  PPG: 115.5                    PPG: 120.8             │
│  DEF: 113.8                    DEF: 109.2             │
│  WIN: 53.7%                    WIN: 73.2%             │
│                                                        │
│              [ SIMULATE GAME ]                         │
│                                                        │
└────────────────────────────────────────────────────────┘

Game Results Display

┌────────────────────────────────────────────────────────┐
│                    FINAL SCORE                         │
│                                                        │
│     LAKERS          108 - 115          CELTICS        │
│                                                        │
├────────────────────────────────────────────────────────┤
│  QUARTER BREAKDOWN                                     │
│  ┌────────┬─────┬─────┬─────┬─────┬───────┐          │
│  │        │ Q1  │ Q2  │ Q3  │ Q4  │ FINAL │          │
│  ├────────┼─────┼─────┼─────┼─────┼───────┤          │
│  │ LAL    │ 28  │ 25  │ 30  │ 25  │  108  │          │
│  │ BOS    │ 32  │ 28  │ 27  │ 28  │  115  │          │
│  └────────┴─────┴─────┴─────┴─────┴───────┘          │
│                                                        │
│  GAME HIGHLIGHTS                                       │
│  • Celtics controlled the game from the 1st quarter   │
│  • High-scoring affair with 223 total points          │
│  • Home court advantage wasn't enough for Lakers      │
│                                                        │
│              [ PLAY AGAIN ]                            │
└────────────────────────────────────────────────────────┘

Styling Approach

Following the existing Hacker News-inspired blog theme:

/* Primary accent color */
.nba-simulator { --accent: #ff6600; }

/* Team cards with team colors */
.team-card {
    border-left: 4px solid var(--team-color);
    background: white;
    padding: 15px;
}

/* Score display */
.final-score {
    font-size: 48px;
    font-weight: bold;
    text-align: center;
}

/* Responsive design */
@media (max-width: 600px) {
    .team-selection { flex-direction: column; }
}

Technical Considerations

API Rate Limits

Scenario Strategy
First load Fetch from API, cache for 24h
Cached data available Use cache, skip API
API fails Fall back to static JSON
Rate limited Fall back to static JSON

Browser Compatibility

  • Required: ES6+ support (const, let, arrow functions, async/await)
  • APIs Used: Fetch API, localStorage
  • Supported: Chrome 60+, Firefox 55+, Safari 11+, Edge 79+

Performance

  • No external dependencies (vanilla JS)
  • Lazy load team data on page load
  • Simulation runs client-side (~10ms)
  • Minimal DOM updates

Future Enhancements

Phase 2 Features

  1. Player-level simulation - Include individual player stats
  2. Playoff series mode - Best-of-7 simulation
  3. Historical matchups - Compare teams across seasons
  4. Share results - Generate shareable game summaries

Phase 3 Features

  1. Season simulation - Full 82-game season
  2. Draft mode - Create custom teams
  3. Leaderboard - Track prediction accuracy
  4. Real-time odds - Compare to betting lines

Implementation Checklist

  • Create _data/nba-teams.json with all 30 teams
  • Create assets/js/nba-simulator.js with simulation engine
  • Create nba-simulator.md main page with UI
  • Add navigation link in _layouts/default.html
  • Add responsive CSS styles
  • Test on mobile devices
  • Add error handling for API failures

Appendix: Team Data Schema

interface Team {
  id: number;
  name: string;           // "Lakers"
  city: string;           // "Los Angeles"
  abbreviation: string;   // "LAL"
  conference: "East" | "West";
  division: string;
  primaryColor: string;   // "#552583"
  secondaryColor: string; // "#FDB927"
  stats: {
    ppg: number;          // Points per game
    oppg: number;         // Opponent points per game
    pace: number;         // Possessions per game
    winPct: number;       // Win percentage (0-1)
  };
}

interface GameResult {
  homeTeam: Team;
  awayTeam: Team;
  homeScore: number;
  awayScore: number;
  quarters: {
    home: number[];       // [28, 25, 30, 25]
    away: number[];       // [32, 28, 27, 28]
  };
  overtime: boolean;
  highlights: string[];
}