Metadata-Version: 2.4
Name: structured-workouts
Version: 0.1.0
Summary: A Python library for creating, parsing, and converting structured workout formats with support for parametrization.
Author-email: Aart Goossens <aart@sweatstack.no>
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

# Structured Workouts

A Python library for creating, parsing, and converting structured workout formats. Built around the **Structured Workout Format (SWF)**, this package enables you to work with workouts from various platforms and convert between different file formats.

## Quick Start

### Installation

```bash
pip install structured-workouts
```

Or using uv:
```bash
uv add structured-workouts
```

### Basic Usage

#### Creating a Workout

```python
from structured_workouts import Workout
from structured_workouts.base import (
    Interval, Section, FixedValue, 
    VolumeQuantity, IntensityQuantity
)

# Create a simple 30-minute threshold workout
workout = Workout(
    title="Threshold Test",
    description="30-minute sustained effort at threshold power",
    content=[
        Section(
            name="Warmup",
            content=[
                Interval(
                    volume=FixedValue(value=10*60, quantity=VolumeQuantity.duration),  # 10 minutes (in seconds)
                    intensity=FixedValue(
                        variable="threshold", 
                        fraction=0.6, 
                        quantity=IntensityQuantity.power
                    )
                )
            ]
        ),
        Section(
            name="Main Set", 
            content=[
                Interval(
                    volume=FixedValue(value=30*60, quantity=VolumeQuantity.duration),  # 30 minutes
                    intensity=FixedValue(
                        variable="threshold",
                        fraction=1.0,
                        quantity=IntensityQuantity.power
                    )
                )
            ]
        ),
        Section(
            name="Cooldown",
            content=[
                Interval(
                    volume=FixedValue(value=10*60, quantity=VolumeQuantity.duration),  # 10 minutes
                    intensity=FixedValue(
                        variable="threshold",
                        fraction=0.5,
                        quantity=IntensityQuantity.power
                    )
                )
            ]
        )
    ]
)

print(f"Created workout: {workout.title}")
```

#### Converting Between Formats

```python
from structured_workouts.parsers import IntervalsICUTextParser

# Export to intervals.icu text format
parser = IntervalsICUTextParser()
intervals_icu_text = parser.to_format(workout)
print("Intervals.icu format:")
print(intervals_icu_text)
```

Output:
```
Warmup
- 10m 60%

Main Set
- 30m 100%

Cooldown
- 10m 50%
```

#### Using the Command Line Interface

Convert workouts between formats using the CLI:

```bash
# Convert from SWF to intervals.icu text format
structured-workouts --from swf --from-file my_workout.json --to intervals-icu-text

# List all available formats
structured-workouts --list-formats

# Convert with automatic format detection
structured-workouts --from-file workout.json
```

## Structured Workout Format (SWF)

The **Structured Workout Format (SWF)** is a JSON-based format designed to be:

- **Simple and readable**: Easy to understand and modify
- **Flexible**: Supports complex workout structures with repeats, sections, and variable intensities
- **Convertible**: Can serve as an intermediate format for converting between other workout formats
- **Parametrizable**: Supports variables for power zones, heart rate zones, etc.

### Key Concepts

- **Duration**: Always specified in seconds (e.g., `600` for 10 minutes)
- **Intensity**: Power or speed, specified as absolute values or as fractions of variables like "threshold"
- **Variables**: Named references like "threshold", "vo2max" for flexible intensity targeting

For detailed format specification, see [README_SWF.md](README_SWF.md).

## Supported Formats

### ✅ Currently Supported

| Format | Import | Export | Notes |
|--------|---------|---------|-------|
| **SWF (JSON)** | ✅ | ✅ | Native format |
| **Intervals.icu Text** | ⚠️ | ✅ | Import is experimental and not feature complete |
| **Intervals.icu API JSON** | ⚠️ | ✅ | Import is experimental and not feature complete |

### 🚧 Planned Support

- ERG files
- MRC files  
- ZWO files (Zwift)
- Garmin Connect JSON format
- FIT files


## Advanced Usage

### Working with Variables

```python
# Create a workout using power zones
workout = Workout(
    title="Power Zone Training",
    content=[
        Interval(
            volume=FixedValue(value=20*60, quantity=VolumeQuantity.duration),
            intensity=FixedValue(
                variable="ftp",  # Functional Threshold Power
                fraction=0.85,   # 85% of FTP
                quantity=IntensityQuantity.power
            )
        )
    ]
)
```

### Complex Workouts with Repeats

```python
from structured_workouts.base import Repeat, RepeatQuantity

# Create intervals: 5x (4 minutes on, 2 minutes recovery)
intervals = Repeat(
    type="repeat",
    count=FixedValue(value=5, quantity=RepeatQuantity.NUMBER),
    content=[
        Interval(
            volume=FixedValue(value=4*60, quantity=VolumeQuantity.duration),
            intensity=FixedValue(variable="threshold", fraction=1.05, quantity=IntensityQuantity.power)
        ),
        Interval(
            volume=FixedValue(value=2*60, quantity=VolumeQuantity.duration), 
            intensity=FixedValue(variable="threshold", fraction=0.6, quantity=IntensityQuantity.power)
        )
    ]
)

workout = Workout(
    title="VO2 Max Intervals",
    content=[Section(name="Intervals", content=[intervals])]
)
```



## Development

### Running Tests

```bash
make test
```

### Project Structure

```
src/structured_workouts/
├── __init__.py           # Main package exports
├── base.py              # Core data structures (Interval, Section, etc.)
├── schema.py            # Pydantic models and validation
├── structured_workout_format.py  # SWF format implementation
├── validation.py        # Additional validation logic
└── parsers/
    ├── base.py          # Abstract parser base class
    ├── intervals_icu_text.py     # Intervals.icu text format parser
    └── intervals_icu_api.py      # Intervals.icu API JSON parser
```

### Upload to Intervals.icu

The package includes a complete example script that creates a workout and uploads it to intervals.icu:

```bash
# Set up your API credentials
export INTERVALS_ICU_API_KEY="your_api_key"
export INTERVALS_ICU_ATHLETE_ID="i"

# Run the upload script
uv run scripts/upload_to_intervals_icu.py
```

See `scripts/upload_to_intervals_icu.py` for a complete working example.

## Contributing

Contributions are welcome! Areas where help is especially appreciated:

1. **New format parsers** (ERG, MRC, ZWO, etc.)
2. **Improving import functionality** for intervals.icu formats
3. **Test coverage** for edge cases
4. **Documentation** and examples

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Background

Although `structured-workouts` is developed by and integrated with SweatStack, it is designed to be a general-purpose library not tied to any specific platform or service.

The main goal is to provide a flexible, standardized way to represent structured workouts that can serve as an intermediate format for converting between different platforms and training systems.