This commit is contained in:
2025-09-26 07:30:15 -07:00
parent 9d7e855713
commit 478d1bb06c
30 changed files with 5584 additions and 31 deletions

5
config/__init__.py Normal file
View File

@@ -0,0 +1,5 @@
"""Configuration management for Garmin Analyser."""
from . import settings
__all__ = ['settings']

79
config/config.yaml Normal file
View File

@@ -0,0 +1,79 @@
# Garmin Analyser Configuration
# Garmin Connect credentials (optional - can be provided via environment variables)
garmin_username: your_garmin_username
garmin_password: your_garmin_password
# Output settings
output_dir: output
log_level: INFO
# Training zones configuration
zones:
# Functional Threshold Power (W)
ftp: 250
# Maximum heart rate (bpm)
max_heart_rate: 185
# Power zones as percentage of FTP
power_zones:
- name: Active Recovery
min: 0
max: 55
percentage: true
- name: Endurance
min: 56
max: 75
percentage: true
- name: Tempo
min: 76
max: 90
percentage: true
- name: Threshold
min: 91
max: 105
percentage: true
- name: VO2 Max
min: 106
max: 120
percentage: true
- name: Anaerobic
min: 121
max: 150
percentage: true
# Heart rate zones as percentage of max HR
heart_rate_zones:
- name: Zone 1 - Recovery
min: 0
max: 60
percentage: true
- name: Zone 2 - Endurance
min: 60
max: 70
percentage: true
- name: Zone 3 - Tempo
min: 70
max: 80
percentage: true
- name: Zone 4 - Threshold
min: 80
max: 90
percentage: true
- name: Zone 5 - VO2 Max
min: 90
max: 100
percentage: true
# Chart settings
charts:
theme: seaborn
figsize: [12, 8]
dpi: 300
# Report settings
reports:
include_charts: true
include_raw_data: false
timezone: UTC

86
config/settings.py Normal file
View File

@@ -0,0 +1,86 @@
"""Configuration settings for Garmin Analyser."""
import os
from pathlib import Path
from typing import Dict, Tuple
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Base paths
BASE_DIR = Path(__file__).parent.parent
DATA_DIR = BASE_DIR / "data"
REPORTS_DIR = BASE_DIR / "reports"
# Create directories if they don't exist
DATA_DIR.mkdir(exist_ok=True)
REPORTS_DIR.mkdir(exist_ok=True)
# Garmin Connect credentials
GARMIN_EMAIL = os.getenv("GARMIN_EMAIL")
GARMIN_PASSWORD = os.getenv("GARMIN_PASSWORD")
# Bike specifications
class BikeConfig:
"""Bike configuration constants."""
# Valid gear configurations
VALID_CONFIGURATIONS: Dict[int, list] = {
38: [14, 16, 18, 20],
46: [16]
}
# Default bike specifications
DEFAULT_CHAINRING_TEETH = 38
BIKE_WEIGHT_LBS = 22
BIKE_WEIGHT_KG = BIKE_WEIGHT_LBS * 0.453592
# Wheel specifications (700x25c)
WHEEL_CIRCUMFERENCE_MM = 2111 # 700x25c wheel circumference
WHEEL_CIRCUMFERENCE_M = WHEEL_CIRCUMFERENCE_MM / 1000
# Gear ratios
GEAR_RATIOS = {
38: {
14: 38/14,
16: 38/16,
18: 38/18,
20: 38/20
},
46: {
16: 46/16
}
}
# Indoor activity detection
INDOOR_KEYWORDS = [
'indoor_cycling', 'indoor cycling', 'indoor bike',
'trainer', 'zwift', 'virtual'
]
# File type detection
SUPPORTED_FORMATS = ['.fit', '.tcx', '.gpx']
# Logging configuration
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Report generation
REPORT_TEMPLATE_DIR = BASE_DIR / "reports" / "templates"
DEFAULT_REPORT_FORMAT = "markdown"
CHART_DPI = 300
CHART_FORMAT = "png"
# Data processing
SMOOTHING_WINDOW = 5 # seconds for gradient smoothing
MIN_WORKOUT_DURATION = 300 # seconds (5 minutes)
MAX_POWER_ESTIMATE = 1000 # watts
# User-specific settings (can be overridden via CLI or environment)
FTP = int(os.getenv("FTP", "250")) # Functional Threshold Power in watts
MAX_HEART_RATE = int(os.getenv("MAX_HEART_RATE", "185")) # Maximum heart rate in bpm
COG_SIZE = int(os.getenv("COG_SIZE", str(BikeConfig.DEFAULT_CHAINRING_TEETH))) # Chainring teeth
# Zones configuration
ZONES_FILE = BASE_DIR / "config" / "zones.json"

20
config/zones.json Normal file
View File

@@ -0,0 +1,20 @@
{
"power": {
"zone1": {"min": 0, "max": 55, "label": "Active Recovery"},
"zone2": {"min": 56, "max": 75, "label": "Endurance"},
"zone3": {"min": 76, "max": 90, "label": "Tempo"},
"zone4": {"min": 91, "max": 105, "label": "Lactate Threshold"},
"zone5": {"min": 106, "max": 120, "label": "VO2 Max"},
"zone6": {"min": 121, "max": 150, "label": "Anaerobic Capacity"},
"zone7": {"min": 151, "max": 999, "label": "Neuromuscular Power"}
},
"heart_rate": {
"zone1": {"min": 0, "max": 60, "label": "Active Recovery"},
"zone2": {"min": 61, "max": 70, "label": "Endurance"},
"zone3": {"min": 71, "max": 80, "label": "Tempo"},
"zone4": {"min": 81, "max": 90, "label": "Lactate Threshold"},
"zone5": {"min": 91, "max": 100, "label": "VO2 Max"},
"zone6": {"min": 101, "max": 110, "label": "Anaerobic Capacity"},
"zone7": {"min": 111, "max": 999, "label": "Neuromuscular Power"}
}
}

66
config/zones.yaml Normal file
View File

@@ -0,0 +1,66 @@
# Custom zones configuration example
# This file can be used to override the default zones in config.yaml
# Functional Threshold Power (W)
ftp: 275
# Maximum heart rate (bpm)
max_heart_rate: 190
# Power zones as percentage of FTP
power_zones:
- name: Recovery
min: 0
max: 50
percentage: true
- name: Endurance
min: 51
max: 70
percentage: true
- name: Tempo
min: 71
max: 85
percentage: true
- name: Sweet Spot
min: 84
max: 97
percentage: true
- name: Threshold
min: 96
max: 105
percentage: true
- name: VO2 Max
min: 106
max: 120
percentage: true
- name: Anaerobic
min: 121
max: 150
percentage: true
# Heart rate zones as percentage of max HR
heart_rate_zones:
- name: Zone 1 - Recovery
min: 0
max: 60
percentage: true
- name: Zone 2 - Endurance
min: 60
max: 70
percentage: true
- name: Zone 3 - Tempo
min: 70
max: 80
percentage: true
- name: Zone 4 - Threshold
min: 80
max: 90
percentage: true
- name: Zone 5 - VO2 Max
min: 90
max: 95
percentage: true
- name: Zone 6 - Neuromuscular
min: 95
max: 100
percentage: true