# Contributing to PrecipGen

## Overview

PrecipGen is focused on providing a reliable, high-performance implementation of the Richardson & Wright (1984) WGEN algorithm. Contributions should align with this core mission.

## Development Principles

### Code Quality Standards

- **PEP 8 compliance** - Follow Python style guidelines
- **Type hints** - All public APIs must have type annotations
- **NumPy docstrings** - Comprehensive documentation for all functions
- **Unit tests** - All public methods require corresponding tests

### Architecture Guidelines

Maintain the modular architecture:

- `precipgen.data` - GHCN data handling, validation, parsing
- `precipgen.engines` - Analytical, simulation, bootstrap engines  
- `precipgen.simulation` - Monte Carlo and analysis components
- `precipgen.config` - Quality presets and configuration
- `precipgen.api` - Standardized interfaces for external integration
- `precipgen.utils` - Exceptions, logging, utilities

### Mathematical Rigor

- **Algorithm transparency** - Clear documentation of mathematical foundation
- **Reference implementation** - Stay true to Richardson & Wright (1984)
- **Validation focus** - Ensure synthetic output matches historical characteristics
- **Statistical soundness** - All statistical methods must be mathematically correct

## Getting Started

### Development Setup

```bash
git clone https://github.com/your-org/precipgen.git
cd precipgen
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -e ".[dev]"
```

### Documentation Development Setup

PrecipGen uses a modern "Docs-as-Code" system with MkDocs, Material theme, and automatic API documentation generation. The system requires minimal configuration and provides professional documentation with zero maintenance.

#### Quick Setup

```bash
# Install documentation dependencies
pip install -e ".[docs]"

# Serve documentation locally for development
mkdocs serve

# Build documentation (output in site/ directory)
mkdocs build
```

#### Detailed Setup Instructions

1. **Install Documentation Dependencies**
   ```bash
   # Option 1: Install with project (recommended)
   pip install -e ".[docs]"
   
   # Option 2: Install manually if needed
   pip install mkdocs>=1.5.0 mkdocs-material>=9.0.0 "mkdocstrings[python]>=0.24.0"
   ```

2. **Start Local Development Server**
   ```bash
   mkdocs serve
   ```
   - Opens at `http://127.0.0.1:8000`
   - Live reload on file changes
   - Matches production site appearance exactly

3. **Build Static Site**
   ```bash
   mkdocs build
   ```
   - Generates static site in `site/` directory
   - Use for testing before deployment
   - Validates all links and references

#### Documentation Architecture

The documentation system uses:

- **MkDocs**: Static site generator with Markdown source files
- **Material Theme**: Professional, responsive design with search
- **mkdocstrings**: Automatic API documentation from Python docstrings
- **GitHub Actions**: Automated deployment to GitHub Pages

#### File Structure

```
docs/
├── index.md              # Homepage (mirrors README.md)
├── api.md               # Auto-generated API reference
├── user_guide.md        # User documentation
├── installation.md      # Installation instructions
├── mathematical_foundation.md  # Technical methodology
└── examples/            # Code examples and tutorials

mkdocs.yml               # Documentation configuration
.github/workflows/docs.yml  # Automated deployment
```

#### Local Development Workflow

1. **Make Changes**
   - Edit Markdown files in `docs/` directory
   - Update docstrings in Python source code
   - Add examples or tutorials

2. **Preview Changes**
   ```bash
   mkdocs serve
   ```
   - View at `http://127.0.0.1:8000`
   - Changes appear immediately (live reload)
   - Test navigation and search functionality

3. **Validate Build**
   ```bash
   mkdocs build
   ```
   - Ensures no build errors
   - Validates all internal links
   - Checks API documentation generation

4. **Commit and Push**
   - Documentation deploys automatically on push to main branch
   - Live site updates within 2-3 minutes
   - Available at `https://jlillywh.github.io/precipgen/`

#### API Documentation

The API documentation is **automatically generated** from Python docstrings:

- **Source**: All docstrings in `precipgen/` package
- **Format**: Google/NumPy style docstrings
- **Output**: Searchable, nested API reference
- **Updates**: Automatic on every code change

**No manual maintenance required** - the system crawls the entire package structure and generates comprehensive documentation.

#### Troubleshooting

**Common Issues and Solutions:**

1. **"mkdocs: command not found"**
   ```bash
   # Ensure documentation dependencies are installed
   pip install -e ".[docs]"
   ```

2. **"No module named 'precipgen'"**
   ```bash
   # Install project in development mode
   pip install -e .
   ```

3. **API documentation missing modules**
   ```bash
   # Ensure Python path includes project root
   export PYTHONPATH="${PYTHONPATH}:$(pwd)"
   mkdocs serve
   ```

4. **Build fails with import errors**
   ```bash
   # Install all project dependencies
   pip install -e ".[dev,docs]"
   ```

5. **Local site doesn't match production**
   ```bash
   # Clear MkDocs cache and rebuild
   rm -rf site/
   mkdocs build
   mkdocs serve
   ```

6. **Search not working locally**
   - Search requires built site (not just serve)
   - Run `mkdocs build` then serve the `site/` directory
   - Or use `mkdocs serve` and wait for initial indexing

7. **Slow build times**
   ```bash
   # Use development mode for faster builds
   mkdocs serve --dev-addr=127.0.0.1:8000
   ```

#### Advanced Configuration

The documentation system is configured in `mkdocs.yml`:

```yaml
# Core configuration
site_name: PrecipGen Documentation
theme:
  name: material
  features:
    - navigation.tabs      # Top-level navigation tabs
    - navigation.sections  # Collapsible sections
    - search.suggest      # Search suggestions
    - search.highlight    # Highlight search terms
    - content.code.copy   # Copy code button

# Automatic API documentation
plugins:
  - mkdocstrings:
      handlers:
        python:
          options:
            docstring_style: google
            show_source: true
            show_root_heading: true
```

**Customization Guidelines:**
- Keep configuration minimal for maintainability
- Use Material theme defaults when possible
- Avoid complex plugins that require maintenance
- Focus on content quality over visual customization

#### Content Guidelines

**Markdown Files:**
- Use clear, descriptive headings
- Include code examples with syntax highlighting
- Link to API documentation using `[text](api.md#module.function)`
- Keep examples practical and working

**Docstring Standards:**
- Follow Google or NumPy docstring format
- Include type hints for all parameters
- Provide working examples in docstrings
- Reference mathematical foundations when applicable

**Examples and Tutorials:**
- Test all code examples before committing
- Use realistic data and scenarios
- Explain both what and why
- Link to relevant API documentation

The documentation system uses MkDocs with Material theme and automatically generates API documentation from docstrings. Local development server runs at `http://127.0.0.1:8000` with live reload.

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=precipgen

# Run specific test file
pytest tests/test_analytical_engine.py
```

### Code Style

```bash
# Format code
black precipgen/
black tests/

# Check style
flake8 precipgen/
flake8 tests/

# Type checking
mypy precipgen/
```

## Contribution Types

### Bug Fixes

1. **Create issue** describing the bug with minimal reproduction case
2. **Write test** that demonstrates the bug
3. **Fix the bug** while maintaining API compatibility
4. **Verify fix** passes all existing tests

### New Features

Features should align with the core WGEN mission:

**Encouraged:**
- Improvements to parameter estimation accuracy
- Enhanced trend detection algorithms
- Better data quality assessment
- Performance optimizations for core algorithms
- Additional validation metrics

**Discouraged:**
- Complex visualization systems (users can use matplotlib directly)
- Template rendering systems (not core to WGEN)
- Premature optimization (decorators, caching layers)
- Orchestration frameworks (keep workflows simple)

### Documentation

- **API documentation** - Auto-generated from docstrings
- **Mathematical explanations** - Include references and theory
- **Working examples** - Demonstrate real-world usage patterns
- **Clear explanations** - Accessible to both beginners and experts

## Pull Request Process

### Before Submitting

1. **Run tests** - Ensure all tests pass
2. **Check style** - Code follows PEP 8
3. **Add tests** - New functionality has corresponding tests
4. **Update docs** - Documentation reflects changes
5. **Verify examples** - Examples still work correctly

### PR Requirements

- **Clear description** - What does this change and why?
- **Issue reference** - Link to related issue if applicable
- **Test coverage** - New code has appropriate tests
- **Documentation** - Public APIs are documented
- **Backward compatibility** - Existing code continues to work

### Review Process

1. **Automated checks** - CI must pass (tests, style, type checking)
2. **Code review** - Maintainer reviews for quality and alignment
3. **Testing** - Verify changes work as expected
4. **Documentation review** - Ensure docs are clear and accurate

## Testing Guidelines

### Unit Tests

Test individual functions and methods:

```python
import pytest
from precipgen.engines.analytical import AnalyticalEngine

def test_monthly_parameter_calculation():
    """Test monthly parameter calculation with known data."""
    # Arrange
    data = create_test_precipitation_data()
    engine = AnalyticalEngine(data)
    
    # Act
    params = engine.calculate_monthly_parameters()
    
    # Assert
    assert len(params) == 12
    assert 0 <= params[1].p_ww <= 1
    assert 0 <= params[1].p_wd <= 1
    assert params[1].alpha > 0
    assert params[1].beta > 0
```

### Integration Tests

Test complete workflows:

```python
def test_complete_analysis_workflow():
    """Test end-to-end analysis workflow."""
    from precipgen import quick_analysis
    
    # Use known good station for testing
    result = quick_analysis("Seattle, WA")
    
    assert result.station_id is not None
    assert result.parameter_manifest is not None
    assert len(result.parameter_manifest.overall_parameters) == 12
```

### Property-Based Tests

Test statistical properties:

```python
from hypothesis import given, strategies as st
import numpy as np

@given(st.lists(st.floats(0, 100), min_size=1000))
def test_gamma_parameter_estimation(precipitation_data):
    """Test gamma parameter estimation properties."""
    data = np.array(precipitation_data)
    wet_data = data[data > 0.1]
    
    if len(wet_data) > 10:  # Need sufficient data
        alpha, beta = estimate_gamma_parameters(wet_data)
        assert alpha > 0
        assert beta > 0
        # Mean should approximately match
        expected_mean = wet_data.mean()
        gamma_mean = alpha * beta
        assert abs(gamma_mean - expected_mean) / expected_mean < 0.1
```

## Code Examples

### Adding a New Engine

```python
from typing import Dict, Any
from .base import Engine

class NewEngine(Engine):
    """
    New engine for specialized precipitation analysis.
    
    Implements the base Engine interface for [specific purpose].
    """
    
    def __init__(self, data: pd.Series, **kwargs):
        """
        Initialize new engine.
        
        Parameters
        ----------
        data : pd.Series
            Time series of precipitation data
        **kwargs
            Additional configuration parameters
        """
        self.data = data
        # Initialize engine-specific attributes
    
    def initialize(self, **kwargs) -> None:
        """Initialize engine state."""
        # Implementation here
        pass
    
    def reset(self, **kwargs) -> None:
        """Reset engine to initial state."""
        # Implementation here
        pass
    
    def get_state(self) -> Dict[str, Any]:
        """Get current engine state."""
        return {
            'data_length': len(self.data),
            # Other state information
        }
```

### Adding Configuration Options

```python
from dataclasses import dataclass
from typing import List

@dataclass
class NewAnalysisConfig:
    """Configuration for new analysis method."""
    
    # Required parameters
    min_data_points: int = 100
    significance_level: float = 0.05
    
    # Optional parameters
    enable_advanced_features: bool = False
    custom_threshold: float = 0.1
    
    def validate(self) -> List[str]:
        """Validate configuration parameters."""
        errors = []
        
        if self.min_data_points < 1:
            errors.append("min_data_points must be positive")
        
        if not (0 < self.significance_level < 1):
            errors.append("significance_level must be between 0 and 1")
        
        return errors
```

## Documentation Standards

### Function Documentation

```python
def calculate_trend_slope(years: np.ndarray, values: np.ndarray, 
                         method: str = 'linear') -> Dict[str, float]:
    """
    Calculate trend slope using linear regression.
    
    Implements trend detection for non-stationary climate analysis
    following the methodology described in Richardson & Wright (1984).
    
    Parameters
    ----------
    years : np.ndarray
        Array of years for trend analysis
    values : np.ndarray
        Array of parameter values corresponding to years
    method : str, default 'linear'
        Regression method ('linear', 'robust')
    
    Returns
    -------
    Dict[str, float]
        Dictionary containing:
        - 'slope': Trend slope per year
        - 'intercept': Y-intercept
        - 'r_squared': Coefficient of determination
        - 'p_value': Statistical significance
    
    Raises
    ------
    InsufficientDataError
        If insufficient data points for reliable trend estimation
    
    Examples
    --------
    >>> years = np.array([1990, 1991, 1992, 1993, 1994])
    >>> values = np.array([0.3, 0.32, 0.31, 0.33, 0.35])
    >>> result = calculate_trend_slope(years, values)
    >>> print(f"Trend: {result['slope']:.6f} per year")
    
    References
    ----------
    Richardson, C.W. and Wright, D.A., 1984. WGEN: A model for generating 
    daily weather variables. US Department of Agriculture, Agricultural 
    Research Service.
    """
    # Implementation here
```

### Class Documentation

```python
class TrendAnalyzer:
    """
    Analyzer for detecting trends in precipitation parameters.
    
    Implements sliding window analysis to detect non-stationary climate
    patterns in WGEN parameters (P(W|W), P(W|D), alpha, beta) across
    seasonal groupings.
    
    The analyzer uses linear regression to detect statistically significant
    trends in parameter evolution over time, supporting climate change
    impact assessment and non-stationary precipitation modeling.
    
    Attributes
    ----------
    window_years : int
        Size of sliding window for trend analysis
    significance_level : float
        Statistical significance threshold for trend detection
    
    Examples
    --------
    >>> analyzer = TrendAnalyzer(window_years=30)
    >>> trends = analyzer.analyze_trends(precipitation_data)
    >>> winter_pww_trend = trends.seasonal_slopes['Winter']['p_ww']
    
    References
    ----------
    Richardson, C.W. and Wright, D.A., 1984. WGEN: A model for generating 
    daily weather variables. US Department of Agriculture, Agricultural 
    Research Service.
    """
```

## Release Process

### Version Numbering

Follow semantic versioning (MAJOR.MINOR.PATCH):

- **MAJOR** - Incompatible API changes
- **MINOR** - New functionality, backward compatible
- **PATCH** - Bug fixes, backward compatible

### Release Checklist

1. **Update version** in `precipgen/__init__.py`
2. **Update CHANGELOG.md** with release notes
3. **Run full test suite** - All tests must pass
4. **Update documentation** - Ensure docs are current
5. **Create release tag** - `git tag v0.1.3`
6. **Build and test package** - Verify installation works
7. **Publish to PyPI** - Make available to users

## Questions?

- **General questions** - Open a GitHub issue
- **Bug reports** - Include minimal reproduction case
- **Feature requests** - Explain use case and alignment with WGEN mission
- **Security issues** - Email maintainers directly

## License

By contributing to PrecipGen, you agree that your contributions will be licensed under the MIT License.