# Oscar Test Data Generation

> Generate realistic synthetic CPAP/sleep therapy test data using the project's builders. Use when creating tests, examples, or validation scenarios that require OSCAR CSV data. Never use real patient data. Use when this capability is needed.

- Skill: `tomevault-io/oscar-test-data-generation` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/oscar-test-data-generation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/oscar-test-data-generation/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/oscar-test-data-generation

---


# OSCAR Test Data Generation

This skill provides patterns for generating realistic synthetic CPAP/sleep therapy test data for the OSCAR Export Analyzer project. All test data should be synthetic—never use real patient information.

## Core Builders

The project provides builder functions in `src/test-utils/builders.js` for generating test data:

### Session Builder

```javascript
import { buildSession } from '../test-utils/builders';

// Build a single CPAP session with custom values
const session = buildSession({
  date: '2024-01-15',
  ahi: 8.5,
  epap: 9.0,
  usage: 7.2,
  leak: 12.5,
});

// Build multiple sessions
const sessions = Array.from({ length: 30 }, (_, i) =>
  buildSession({
    date: new Date(2024, 0, i + 1).toISOString().split('T')[0],
    ahi: 5 + Math.random() * 10,
    epap: 8 + Math.random() * 2,
    usage: 6 + Math.random() * 3,
  }),
);
```

### Fitbit Data Builder

```javascript
import {
  buildFitbitHeartRate,
  buildFitbitSleepStage,
} from '../test-utils/fitbitBuilders';

// Heart rate data
const hrData = buildFitbitHeartRate({
  date: '2024-01-15',
  bpm: 65,
  confidence: 3,
});

// Sleep stage data
const sleepStage = buildFitbitSleepStage({
  date: '2024-01-15',
  level: 'deep',
  seconds: 3600,
});
```

## Common Test Scenarios

### High AHI Cases

```javascript
// Severe sleep apnea scenario
const highAhiSession = buildSession({
  date: '2024-01-15',
  ahi: 42.3, // Severe: > 30
  centralApneas: 15,
  obstructiveApneas: 25,
  hypopneas: 10,
  epap: 10.5,
  usage: 6.8,
  leak: 18.2,
});
```

### Zero Usage / Missing Data

```javascript
// Night with no therapy
const noUsageSession = buildSession({
  date: '2024-01-16',
  usage: 0,
  ahi: null, // No AHI when not used
  epap: null,
});
```

### Edge Case Values

```javascript
// Boundary values for validation testing
const edgeCases = [
  buildSession({ ahi: 0, epap: 4.0 }), // Minimum values
  buildSession({ ahi: 150, epap: 25 }), // Maximum values
  buildSession({ ahi: -1 }), // Invalid: negative
  buildSession({ date: 'invalid-date' }), // Invalid date format
];
```

### Time-Series Patterns

```javascript
// Therapy adjustment period (ramping up pressure)
const titrationPeriod = Array.from({ length: 14 }, (_, i) =>
  buildSession({
    date: new Date(2024, 0, i + 1).toISOString().split('T')[0],
    epap: 7 + i * 0.3, // Gradual increase
    ahi: 15 - i * 0.8, // Improving AHI
    usage: 7 + Math.random() * 0.5,
  }),
);

// Weekly pattern (worse on weekends)
const weeklyPattern = Array.from({ length: 30 }, (_, i) => {
  const dayOfWeek = i % 7;
  const isWeekend = dayOfWeek === 5 || dayOfWeek === 6;

  return buildSession({
    date: new Date(2024, 0, i + 1).toISOString().split('T')[0],
    ahi: isWeekend ? 12 + Math.random() * 5 : 6 + Math.random() * 3,
    usage: isWeekend ? 5 + Math.random() * 2 : 7 + Math.random() * 1,
  });
});
```

### Correlation Scenarios (CPAP + Fitbit)

```javascript
// Correlated CPAP and Fitbit data
const correlatedNight = {
  cpap: buildSession({
    date: '2024-01-15',
    ahi: 25.3,
    usage: 7.2,
    epap: 9.0,
  }),
  fitbit: {
    heartRate: Array.from({ length: 24 }, (_, hour) =>
      buildFitbitHeartRate({
        date: '2024-01-15',
        time: `${hour}:30:00`,
        bpm: 60 + (hour < 6 || hour > 22 ? 0 : 15), // Lower during sleep
      }),
    ),
    sleepStages: [
      buildFitbitSleepStage({
        date: '2024-01-15',
        level: 'light',
        seconds: 3600,
      }),
      buildFitbitSleepStage({
        date: '2024-01-15',
        level: 'deep',
        seconds: 2400,
      }),
      buildFitbitSleepStage({
        date: '2024-01-15',
        level: 'rem',
        seconds: 1800,
      }),
    ],
  },
};
```

## CSV Export Generation

```javascript
// Generate CSV string for upload testing
function generateCsvFromSessions(sessions) {
  const headers = ['Date', 'AHI', 'EPAP', 'Usage (hours)', 'Leak Rate'];
  const rows = sessions.map((s) =>
    [s.date, s.ahi, s.epap, s.usage, s.leak].join(','),
  );

  return [headers.join(','), ...rows].join('\n');
}

const csvContent = generateCsvFromSessions(sessions);
```

## Security Reminders

**NEVER use real patient data in test files:**

- ❌ Don't copy real OSCAR CSV exports
- ❌ Don't use actual AHI values from real patients
- ❌ Don't include real timestamps or identifiable patterns
- ✅ Use synthetic data with builder functions
- ✅ Document test scenarios by description ("high AHI case"), not values
- ✅ Generate random but realistic values

## Test Constants

```javascript
// Medical reference values (from testConstants.js)
export const MEDICAL_THRESHOLDS = {
  AHI_NORMAL: 5,
  AHI_MILD: 15,
  AHI_MODERATE: 30,
  EPAP_MIN: 4.0,
  EPAP_MAX: 25.0,
  USAGE_COMPLIANT: 4.0, // Hours per night
};
```

## Resources

- **Builder API**: `src/test-utils/builders.js`
- **Fitbit builders**: `src/test-utils/fitbitBuilders.js`
- **Test constants**: `src/test-utils/testConstants.js`
- **Mock hooks**: `src/test-utils/mockHooks.js`
- **Fixtures**: `src/test-utils/fixtures/`

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/kabaka) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-15 -->

