117 lines
3.8 KiB
Python
117 lines
3.8 KiB
Python
"""Disposable UI fixture on port 5001. Synthetic friend-shared data; never reads Garmin files."""
|
|
|
|
import math
|
|
import sys
|
|
from datetime import UTC, datetime, timedelta
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from waitress import serve
|
|
|
|
from app import create_app
|
|
from app.display import persist_analysis
|
|
from app.extensions import db
|
|
from app.models import Activity, SavedAnalysis, User
|
|
from app.records import persist_efforts
|
|
|
|
app = create_app(
|
|
{
|
|
"SQLALCHEMY_DATABASE_URI": "sqlite://",
|
|
"SECRET_KEY": "disposable-ui-fixture",
|
|
"LOCAL_SETUP": False,
|
|
"RATELIMIT_ENABLED": False,
|
|
}
|
|
)
|
|
with app.app_context():
|
|
db.create_all()
|
|
user = User(
|
|
username="preview",
|
|
display_name="Preview Runner",
|
|
email="preview@example.test",
|
|
password_hash="disabled",
|
|
)
|
|
db.session.add(user)
|
|
db.session.flush()
|
|
analysis_preview = "--analysis" in sys.argv
|
|
for i in range(70 if analysis_preview else 5):
|
|
effort_hr = 157 + i % 3 if i < 8 else 141 + i % 5
|
|
samples = [
|
|
{
|
|
"point": [51.507 + 0.007 * math.sin(n / 70), -0.14 + n / 25000],
|
|
"distance": n * (15 if analysis_preview else 20),
|
|
"time": n * 5,
|
|
"speed": 3 + 0.02 * math.sin(n / 20)
|
|
if analysis_preview
|
|
else 2.8 + 0.3 * math.sin(n / 20),
|
|
"heart_rate": effort_hr + math.sin(n / 30)
|
|
if analysis_preview
|
|
else 140 + 12 * math.sin(n / 30),
|
|
"elevation": 10 + n / 30,
|
|
}
|
|
for n in range(300)
|
|
]
|
|
db.session.add(
|
|
Activity(
|
|
owner_id=user.id,
|
|
source_key=f"fixture:{i}",
|
|
title=[
|
|
"Morning miles",
|
|
"A little further",
|
|
"Easy Sunday",
|
|
"Tempo session",
|
|
"Evening loop",
|
|
][i % 5],
|
|
started_at=datetime.now(UTC) - timedelta(days=i * (2 if analysis_preview else 5)),
|
|
distance_m=6000 if analysis_preview else 6000 + i * 700,
|
|
duration_s=1980 if analysis_preview else 2100 + i * 200,
|
|
elevation_m=30 if analysis_preview else 38 + i * 7,
|
|
avg_hr=effort_hr if analysis_preview else 145,
|
|
sport="running",
|
|
visibility="friends",
|
|
samples=samples,
|
|
laps=[{"distance": 1000, "duration": 350, "pace": 350, "heart_rate": 145}] * 6,
|
|
)
|
|
)
|
|
for row in list(db.session.new):
|
|
if isinstance(row, Activity):
|
|
persist_efforts(row)
|
|
persist_analysis(row)
|
|
if analysis_preview:
|
|
from app.stats_presets import PRESETS
|
|
|
|
names = [
|
|
"HR at comparable pace",
|
|
"Workload context",
|
|
"HR in steady segments",
|
|
"Easy and harder volume",
|
|
]
|
|
for position, name in enumerate(names):
|
|
preset = next(preset for preset in PRESETS if preset["name"] == name)
|
|
db.session.add(
|
|
SavedAnalysis(
|
|
owner_id=user.id,
|
|
name=name,
|
|
collection="Effort investigation",
|
|
query=preset["query"],
|
|
pinned=True,
|
|
position=position,
|
|
width="half",
|
|
view="chart",
|
|
notes="Synthetic preview data.",
|
|
)
|
|
)
|
|
db.session.commit()
|
|
|
|
# Test-only auto-login, isolated to this ephemeral process/database.
|
|
from flask_login import login_user
|
|
|
|
|
|
@app.before_request
|
|
def preview_login():
|
|
login_user(db.session.get(User, 1))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
serve(app, host="127.0.0.1", port=5001, threads=1)
|