mirror of
https://github.com/sstent/FitTrack_ReportGenerator.git
synced 2026-01-26 00:52:03 +00:00
This commit introduces the initial version of the FitTrack Report Generator, a FastAPI application for analyzing workout files. Key features include: - Parsing of FIT, TCX, and GPX workout files. - Analysis of power, heart rate, speed, and elevation data. - Generation of summary reports and charts. - REST API for single and batch workout analysis. The project structure has been set up with a `src` directory for core logic, an `api` directory for the FastAPI application, and a `tests` directory for unit, integration, and contract tests. The development workflow is configured to use Docker and modern Python tooling.
103 lines
3.8 KiB
Python
103 lines
3.8 KiB
Python
import pytest
|
|
import pandas as pd
|
|
from datetime import datetime, timedelta
|
|
from src.core.workout_data import WorkoutData, WorkoutMetadata, PowerData, HeartRateData, SpeedData, ElevationData
|
|
from src.core.chart_generator import ChartGenerator
|
|
|
|
@pytest.fixture
|
|
def sample_workout_data():
|
|
# Create dummy time-series data
|
|
timestamps = pd.to_datetime([datetime(2025, 1, 1, 10, 0, 0) + timedelta(seconds=i) for i in range(600)])
|
|
power = pd.Series([150 + 50 * (i % 10) for i in range(600)], index=timestamps)
|
|
heart_rate = pd.Series([120 + 10 * (i % 5) for i in range(600)], index=timestamps)
|
|
speed = pd.Series([5 + 2 * (i % 7) for i in range(600)], index=timestamps)
|
|
altitude = pd.Series([100 + 10 * (i % 12) for i in range(600)], index=timestamps)
|
|
|
|
time_series_data = pd.DataFrame({
|
|
"power": power,
|
|
"heart_rate": heart_rate,
|
|
"speed": speed,
|
|
"altitude": altitude
|
|
})
|
|
|
|
metadata = WorkoutMetadata(
|
|
start_time=datetime(2025, 1, 1, 10, 0, 0),
|
|
duration=timedelta(minutes=10),
|
|
device="Garmin",
|
|
file_type="FIT"
|
|
)
|
|
|
|
power_data = PowerData(
|
|
raw_power_stream=power.tolist(),
|
|
average_power=power.mean(),
|
|
normalized_power=power.mean() * 1.05, # Dummy value
|
|
intensity_factor=0.8,
|
|
training_stress_score=50,
|
|
zone_distribution={'Z1': 100, 'Z2': 200, 'Z3': 300}
|
|
)
|
|
|
|
heart_rate_data = HeartRateData(
|
|
raw_hr_stream=heart_rate.tolist(),
|
|
average_hr=heart_rate.mean(),
|
|
max_hr=heart_rate.max(),
|
|
zone_distribution={'Z1': 150, 'Z2': 250, 'Z3': 200}
|
|
)
|
|
|
|
speed_data = SpeedData(
|
|
raw_speed_stream=speed.tolist(),
|
|
average_speed=speed.mean(),
|
|
max_speed=speed.max(),
|
|
zone_distribution={'S1': 100, 'S2': 200, 'S3': 300}
|
|
)
|
|
|
|
elevation_data = ElevationData(
|
|
raw_elevation_stream=altitude.tolist(),
|
|
total_ascent=100,
|
|
total_descent=50,
|
|
max_elevation=200,
|
|
min_elevation=50
|
|
)
|
|
|
|
return WorkoutData(
|
|
metadata=metadata,
|
|
time_series_data=time_series_data,
|
|
power_data=power_data,
|
|
heart_rate_data=heart_rate_data,
|
|
speed_data=speed_data,
|
|
elevation_data=elevation_data
|
|
)
|
|
|
|
def test_generate_power_curve_chart(sample_workout_data, tmp_path):
|
|
chart_generator = ChartGenerator(sample_workout_data)
|
|
output_file = tmp_path / "power_curve.png"
|
|
chart_generator.generate_power_curve_chart(output_file)
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0
|
|
|
|
def test_generate_elevation_profile_chart(sample_workout_data, tmp_path):
|
|
chart_generator = ChartGenerator(sample_workout_data)
|
|
output_file = tmp_path / "elevation_profile.png"
|
|
chart_generator.generate_elevation_profile_chart(output_file)
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0
|
|
|
|
def test_generate_power_zone_distribution_chart(sample_workout_data, tmp_path):
|
|
chart_generator = ChartGenerator(sample_workout_data)
|
|
output_file = tmp_path / "power_zone_distribution.png"
|
|
chart_generator.generate_zone_distribution_chart("power", output_file)
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0
|
|
|
|
def test_generate_hr_zone_distribution_chart(sample_workout_data, tmp_path):
|
|
chart_generator = ChartGenerator(sample_workout_data)
|
|
output_file = tmp_path / "hr_zone_distribution.png"
|
|
chart_generator.generate_zone_distribution_chart("heart_rate", output_file)
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0
|
|
|
|
def test_generate_speed_zone_distribution_chart(sample_workout_data, tmp_path):
|
|
chart_generator = ChartGenerator(sample_workout_data)
|
|
output_file = tmp_path / "speed_zone_distribution.png"
|
|
chart_generator.generate_zone_distribution_chart("speed", output_file)
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0 |