# Ski DIN Calculator

A comprehensive TypeScript library for calculating ski binding DIN (Deutsches Institut für Normung) release values based on skier characteristics and skiing style.

## Installation

```bash
npm install ski-din-calculator
```

## Features

- ✅ **Two calculation methods**: Function-based (metric) and class-based (imperial)
- ✅ **Full TypeScript support** with detailed type definitions
- ✅ **Input validation** with descriptive error messages
- ✅ **Unit conversion utilities** for height and weight
- ✅ **Comprehensive test coverage**
- ✅ **ISO 11088 compliant** DIN calculation standards

## Quick Start

### Function-based Calculator (Metric Units)

```typescript
import { calculateDIN, convertLbsToKg, convertInchesToCm } from 'ski-din-calculator';

// Calculate DIN for a skier
const result = calculateDIN(
  178,        // height in cm
  75,         // weight in kg  
  28,         // age
  2,          // skill level (1=Cautious, 2=Moderate, 3=Aggressive)
  305         // boot sole length in mm
);

console.log(`DIN Value: ${result?.dinValue}`);
console.log(`Skier Code: ${result?.skierCode}`);

// With unit conversion
const heightCm = convertInchesToCm(70);    // 177.8 cm
const weightKg = convertLbsToKg(160);      // 72.57 kg

const result2 = calculateDIN(heightCm, weightKg, 32, 3, 310);
```

### Class-based Calculator (Imperial Units)

```typescript
import { DinCalculator, SkierProfile } from 'ski-din-calculator';

const calculator = new DinCalculator();

const profile: SkierProfile = {
  height: 70,       // inches
  weight: 160,      // pounds
  age: 28,
  skill: 2,         // 1=Cautious, 2=Moderate, 3=Aggressive
  soleLength: 305   // millimeters
};

const dinValue = calculator.calculateDIN(profile);
console.log(`DIN Value: ${dinValue}`);
```

## API Reference

### Functions

#### `calculateDIN(height, weight, age, skill, bootSoleLength)`

Calculates DIN value using metric units.

**Parameters:**
- `height` (number): Height in centimeters (1-250)
- `weight` (number): Weight in kilograms (1-150) 
- `age` (number): Age in years (3-100)
- `skill` (number): Skill level - 1 (Cautious), 2 (Moderate), 3 (Aggressive)
- `bootSoleLength` (number): Boot sole length in millimeters (200-360)

**Returns:** `DINResult | null`

**Throws:**
- `InvalidHeightError`: Height outside valid range
- `InvalidWeightError`: Weight outside valid range
- `InvalidAgeError`: Age outside valid range
- `InvalidSkierTypeError`: Invalid skill level
- `InvalidBootSoleLengthError`: Boot sole length outside valid range

#### `lookupDIN(skierCode, bootSoleLength)`

Direct DIN lookup by skier code.

**Parameters:**
- `skierCode` (number): Numeric skier code (1-16)
- `bootSoleLength` (number): Boot sole length in millimeters

**Returns:** `DINResult | null`

### Utility Functions

```typescript
import { 
  convertLbsToKg, 
  convertKgToLbs, 
  convertInchesToCm, 
  convertCmToInches 
} from 'ski-din-calculator';

// Weight conversions
convertLbsToKg(160);    // 72.57 kg
convertKgToLbs(75);     // 165.35 lbs

// Height conversions  
convertInchesToCm(70);  // 177.8 cm
convertCmToInches(180); // 70.87 inches
```

### Class-based Calculator

```typescript
import { DinCalculator, SkierProfile } from 'ski-din-calculator';

const calculator = new DinCalculator();
const dinValue = calculator.calculateDIN(profile);
```

### Types

#### `DINResult`

```typescript
interface DINResult {
  skierCode: string;              // Letter code (A-P)
  dinValue: number;               // Recommended DIN setting
  twistRange: [number, number];   // Acceptable twist release range
  forwardLeanRange: [number, number]; // Forward lean release range
  torqueRange: [number, number];  // Torque release range
  originalSkierCode: number;      // Numeric skier code used
  safetyWarning: string;          // Safety warnings if applicable
  suggestedRecheckInterval: string; // When to recheck DIN
}
```

#### `SkierProfile`

```typescript
interface SkierProfile {
  height: number;      // Height in inches
  weight: number;      // Weight in pounds  
  age: number;         // Age in years
  skill: number;       // Skill level (1-3)
  soleLength: number;  // Boot sole length in mm
}
```

## Skill Levels

- **1 - Cautious**: Beginner to intermediate skiers who prefer controlled, comfortable skiing
- **2 - Moderate**: Intermediate skiers who ski at moderate speeds with good control
- **3 - Aggressive**: Advanced/expert skiers who ski fast and aggressively

## Error Handling

The library uses specific error types for better error handling:

```typescript
import { calculateDIN, InvalidHeightError, InvalidWeightError } from 'ski-din-calculator';

try {
  const result = calculateDIN(500, 75, 28, 2, 305); // Invalid height
} catch (error) {
  if (error instanceof InvalidHeightError) {
    console.log(`Height error: ${error.message}`);
    console.log(`Invalid value: ${error.value}`);
  }
}
```

## Safety Warning

⚠️ **Important**: This calculator is for reference only. Always consult a qualified ski technician for final DIN settings. Incorrect DIN settings can lead to serious injury.

## Contributing

Contributions are welcome! Please read our contributing guidelines and ensure all tests pass:

```bash
npm test
npm run build
```

## License

MIT © [Kris Steigerwald](https://github.com/your-username)

---

*This library implements the ISO 11088 standard for ski binding release calculations.*