kinemotion 0.48.0__tar.gz → 0.49.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kinemotion might be problematic. Click here for more details.
- kinemotion-0.49.0/.basic-memory/development/feature-request-system-configuration.md +97 -0
- kinemotion-0.49.0/.basic-memory/development/supabase-database-integration-setup.md +104 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/CHANGELOG.md +18 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/PKG-INFO +1 -1
- kinemotion-0.49.0/backend/src/kinemotion_backend/analysis_api.py +303 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/src/kinemotion_backend/app.py +66 -2
- kinemotion-0.49.0/backend/src/kinemotion_backend/database.py +298 -0
- kinemotion-0.49.0/backend/src/kinemotion_backend/models.py +108 -0
- kinemotion-0.49.0/backend/src/kinemotion_backend/types.py +5 -0
- kinemotion-0.49.0/backend/supabase-schema.sql +148 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/README.md +2 -0
- kinemotion-0.49.0/docs/development/feature-request-system.md +191 -0
- kinemotion-0.49.0/docs/development/feedback-system-setup.md +192 -0
- kinemotion-0.49.0/frontend/src/components/FeatureRequestButton.tsx +103 -0
- kinemotion-0.49.0/frontend/src/components/FeedbackForm.css +308 -0
- kinemotion-0.49.0/frontend/src/components/FeedbackForm.tsx +212 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/ResultsDisplay.tsx +190 -0
- kinemotion-0.49.0/frontend/src/config/links.ts +46 -0
- kinemotion-0.49.0/frontend/src/hooks/useDatabaseStatus.ts +62 -0
- kinemotion-0.49.0/frontend/src/test/setup.ts +21 -0
- kinemotion-0.49.0/frontend/src/vite-env.d.ts +35 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/pyproject.toml +1 -1
- {kinemotion-0.48.0 → kinemotion-0.49.0}/sonar-project.properties +1 -1
- {kinemotion-0.48.0 → kinemotion-0.49.0}/uv.lock +1 -1
- kinemotion-0.48.0/frontend/src/test/setup.ts +0 -1
- kinemotion-0.48.0/frontend/src/vite-env.d.ts +0 -9
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/api/api-reference-quick-commands.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/api/cloud-run-cpu-specifications-investigation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/api/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/auth-provider-comparison-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/auth-providers-comparison-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-authentication-quick-start.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-authentication-setup-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-authentication-technical-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-google-oauth-setup-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-production-setup-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/authentication/supabase-quick-start-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/camera-angle-empirical-validation-results-45-superior-for-media-pipe.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/camera-perspective-analysis-45deg-vs-lateral.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/cmj-landing-detection-window-validation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/cmj-physiological-bounds-for-validation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/cmj-validation-implementation-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/drop-jump-vs-cmj-key-differences.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/biomechanics/technical-implementation-45deg-perspective-correction.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/codebase/codebase-architecture-overview.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/codebase/validation-architecture-visual-hierarchy-after-refactoring.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/codebase/validation-code-duplication-evidence.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/codebase/validation-module-architecture-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/codebase/validation-refactoring-complete-architecture-improvement.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/automated-deployment-setup-git-hub-actions-with-workload-identity-federation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/backend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/backend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/cloud-run-security-least-privilege-service-account-setup.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/cors-and-memory-issues-production-debugging-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/current-kinemotion-architecture-correct-deployment-setup.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/frontend-repository-split-migration-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/frontend-repository-split-step-by-step-execution-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/production-deployment-guide-vercel-google-cloud-run.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/quick-deployment-commands-vercel-and-cloud-run.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/deployment/vercel-monorepo-deployment-best-practice.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/athlete-pose3d-and-cross-platform-determinism-investigation-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/athlete-pose3d-final-strategy-accuracy-and-robustness.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/athlete-pose3d-media-pipe-enhancement-plan.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/athlete-pose3d-phase-1-implementation-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/backend-authentication-and-logging-status.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/backend-code-coverage-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/backend-code-duplication-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/backend-kinemotion-decoupling-strategy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/backend-sonar-cloud-integration-status.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/basic-memory-naming-hook-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/ci-caching-issue-investigation-deep-squat-test-failure.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/ci-vs-local-test-failure-investigation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/claude-code-hook-configuration.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/cmj-phase-detection-testing-gap-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/commit-review-r2-video-storage-migration-fe74d1f.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/comprehensive-timing-instrumentation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/cross-platform-determinism-analysis-final-results.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/development-standards-quality-gates.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/drop-jump-detection-complete-fix-all-metrics-within-target.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/drop-jump-detection-failure-analysis-per-video-breakdown.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/drop-jump-fix-drop-start-successful-landing-and-takeoff-remain.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/follow-up-improvements-to-r2-video-storage-migration.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/frontend-dependencies-analysis-nov-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/google-oauth-setup-script-final-review-production-ready.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/google-oauth-setup-script-review-issues-and-recommendations.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/hook-complete-audit-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/hook-configuration-audit.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/hook-quick-reference.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/keyboard-interrupt-test-suite-failure-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/non-deterministic-analysis-root-cause-and-solution.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/optimal-timing-implementation-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/p0-p1-p2-test-suite-fixes-final-report.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/pose-detection-baseline-evaluation-results.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/pose-detection-optimization-complete-success-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/pose-detection-parameter-optimization-framework.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/structured-logging-implementation-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/structured-logging-implementation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/supabase-dashboard-navigation-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-coverage-asymmetry-analysis-cmj-vs-drop-jump.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-coverage-equivalence-achievement-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-suite-comprehensive-review-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-suite-comprehensive-review-structure-and-gaps.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-suite-p0-p1-p2-fixes-complete-report.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/test-suite-p0-p1-p2-fixes-progress-report.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/unused-and-experimental-features-strategy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/unused-code-detection-prompt-template.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/unused-code-identification-and-decorator-application-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/unused-code-verification-final-pass-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/using-multiple-mcp-reasoning-servers-simultaneously.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/velocity-threshold-empirical-validation-study.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/development/vercel-authentication-options-for-user-id-tracking.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/documentation-audit-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/issue-12-mvp-scaffolding-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/issue-12-unblocked-tasks-breakdown.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/issue-12-use-real-metrics-now.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/kinemotion-project-setup-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/kinemotion-supabase-production-configuration.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/mcp-sequential-thinking-alternatives-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/performance-optimization-pose-tracker-pool-timing-instrumentation-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/project-state-summary-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/specialized-subagents-routing-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/supabase-setup-instructions-for-kinemotion.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/project-management/version-mismatch-analysis-kinemotion-0370-vs-0300.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/deployment-decision-analysis-for-kinemotion.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/mvp-feedback-collection-plan.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/mvp-first-strategic-direction.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/mvp-validation-checkpoints.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/pose2sim-migration-evaluation-and-strategy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/strategic-priority-tasks-current-roadmap.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.basic-memory/strategy/third-party-auth-providers-with-free-tiers-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/biomechanics-specialist.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/computer-vision-engineer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/devops-cicd-engineer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/frontend-developer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/ml-data-scientist.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/project-manager.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/python-backend-developer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/qa-test-engineer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/agents/technical-writer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.claude/settings.local.json +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.cursor/mcp.json +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.dockerignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.envrc +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.gitattributes +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/dependabot.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/pull_request_template.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/workflows/deploy-backend.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/workflows/docs.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/workflows/release.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.github/workflows/test.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.mcp.json +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.pre-commit-config.yaml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.readthedocs.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/backend-cors-fastapi-middleware-order.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/camera-perspective-validation-study.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/code_style_and_conventions.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/current-project-architecture.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/deployment-checklist-and-known-issues.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/deployment-setup-complete.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/github-project-setup-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/mvp-first-strategy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/mvp-roadmap-and-priorities.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/project_overview.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/specialist-agents-routing.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/memories/suggested_commands.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.serena/project.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.tool-versions +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/.vercelignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/CLAUDE.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/CODE_OF_CONDUCT.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/CONTRIBUTING.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/Dockerfile +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/GEMINI.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/LICENSE +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/SECURITY.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/.dockerignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/.env.example +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/Dockerfile +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/docs/fly-deployment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/docs/implementation-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/docs/setup.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/docs/tests.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/pyproject.toml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/src/kinemotion_backend/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/src/kinemotion_backend/auth.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/src/kinemotion_backend/logging_config.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/src/kinemotion_backend/middleware.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/conftest.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/test_api_endpoints.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/test_error_handling.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/test_health.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/test_r2_integration.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/backend/tests/test_validation.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/api/cmj.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/api/core.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/api/dropjump.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/api/overview.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/agents-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/errors-findings.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/test-suite-review-december-2025.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/testing-standards.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/testing.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/type-hints.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/validation-plan.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/validation-roadmap.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/development/wallball-norep-detection.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/bulk-processing.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/camera-setup.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/cloud-run-deployment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/cmj-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/cmj-recording-protocol-es.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/cmj-recording-protocol.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/deployment-checklist.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/local-testing.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/guides/setup-issue-12.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/index.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/quick-start.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/reference/cloud-run-quick-reference.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/reference/json-output-format.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/reference/json-structure-comparison.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/reference/parameters.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/reference/pose-systems.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/HOW-TO-FIND-DOIS.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/dois.txt +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/download.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/pyproject.toml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/paper-downloader/uv.lock +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/sports-biomechanics-pose-estimation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/MANUAL-DOWNLOAD-GUIDE.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/convert_pdfs.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/athlete-monitoring/2018_Ward_Putting-i-in-Team.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2011_Harper_10-to-5-Jump-Test.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2014_Samozino_FV-Imbalance.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/jump-performance/2022_Wells_Golf-Clubhead-CMJ.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2016_Moore_Economical-Running-Technique.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/smartphone-technology/2022_Bishop_MyJumpLab-Validation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/markdown/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/online-references-for-papers.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2001_Foster_Session-RPE-Training-Monitoring.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2015_Buchheit_GPS-Accelerometers-Stride-Stiffness.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Flatt_HRV-Recovery-Swimmers.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Saw_Training-Camps-Monitoring.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/athlete-monitoring/2018_Ward_Putting-i-in-Team.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2011_Petersen_Nordic-Hamstring-Prevention.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2011_Wilk_Shoulder-GIRD-Baseball-Pitchers.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2012_Hewit_Multidirectional-Leg-Asymmetry.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Ford_Hip-Neuromuscular-Exercise-Valgus.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Mosler_Hip-Groin-Pain-Factors.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2015_Sconce_Nordic-Hamstring-Validity.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2016_Mendez-Villanueva_Hamstring-MRI-Regional.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2016_Read_Youth-Soccer-Injury-Risk.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mason-Mackay_Ankle-Dorsiflexion-Landing.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2017_Mendiguchia_Hamstring-Treatment-Algorithm.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2018_Balsalobre-Fernandez_Ankle-Dorsiflexion-App.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2018_Bramah_Pathological-Gait-Running-Injuries.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/injury-prevention/2020_Fidai_Fatigue-Knee-Valgus-Youth.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2011_Harper_10-to-5-Jump-Test.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2012_Samozino_Optimal-Force-Velocity-Profile.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2014_Samozino_FV-Imbalance.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2016_Jimenez-Reyes_Force-Velocity-Training.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2016_Morin-Samozino_Power-Force-Velocity-Profiles.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2018_Garcia-Ramos_Two-Point-Method-Optimization.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/jump-performance/2022_Wells_Golf-Clubhead-CMJ.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2005_Morin_Running-Stiffness-Measurement.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2015_Balsalobre-Fernandez_Strength-Training-Running-Economy.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Balsalobre-Fernandez_iPhone-Running-Mechanics.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2016_Moore_Economical-Running-Technique.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Filter_Curve-Sprint-Test-Soccer.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2020_Harper_Horizontal-Deceleration-Radar.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2021_vanOeveren_Running-Biomechanics-Synthesis.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/running-biomechanics/2024_Bramah_Sprint-Mechanics-Assessment-Score.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/smartphone-technology/2015_Balsalobre-Fernandez_iPhone-Vertical-Jump.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/smartphone-technology/2022_Bishop_MyJumpLab-Validation.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2011_Jidovtseff_Load-Velocity-1RM-Prediction.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Conceicao_Movement-Velocity-Lower-Limb.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2016_Pareja-Blanco_Velocity-Loss-Training.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2017_Balsalobre-Fernandez_Barbell-Velocity-1RM.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2020_Balsalobre-Fernandez_Barbell-Trajectory-Snatch.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/research/thirdparty/pdfs/velocity-based-training/2023_Balsalobre-Fernandez_AI-Barbell-Velocity.pdf +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/1-STRATEGIC_SUMMARY.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/2-STRATEGIC_ANALYSIS.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/MVP_FEEDBACK_COLLECTION.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/MVP_VALIDATION_CHECKPOINTS.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/STYLE_GUIDE.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/02-technical-assessment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/03-refactoring-roadmap.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BACKEND_ARCHITECTURE/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BIOMECHANICS/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BIOMECHANICS/02-technical-assessment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BIOMECHANICS/03-reference-guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/BIOMECHANICS/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/COMPUTER_VISION/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/COMPUTER_VISION/02-real-time-architecture.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/COMPUTER_VISION/03-implementation-checklist.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/COMPUTER_VISION/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/01-agent-consensus.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/02-critical-findings.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/03-roadmap-adjustments.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/04-decision-points.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/risk-register.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/CONSOLIDATED/timeline-roadmap.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/DEVOPS_CI_CD/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/DEVOPS_CI_CD/02-infrastructure-assessment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/DEVOPS_CI_CD/03-implementation-roadmap.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/DEVOPS_CI_CD/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/02-technical-assessment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/03-parameter-specifications.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/ML_DATA_SCIENCE/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/QA_TESTING/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/QA_TESTING/02-roadmap-assessment.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/QA_TESTING/03-testing-checklists.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/QA_TESTING/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/TECHNICAL_WRITING/01-executive-summary.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/TECHNICAL_WRITING/02-documentation-strategy.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/TECHNICAL_WRITING/03-action-plan.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/agent-assessments/TECHNICAL_WRITING/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/strategy/pose2sim-migration-evaluation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/technical/framerate.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/technical/implementation-details.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/technical/imu-metadata.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/technical/real-time-analysis.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/technical/triple-extension.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/translations/es/camera-setup.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/validation/determinism-test.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/validation/known-height-validation.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/docs/validation-status.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/examples/bulk/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/examples/bulk/bulk_processing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/examples/bulk/simple_example.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/examples/programmatic_usage.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.editorconfig +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.env.example +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.gitattributes +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.yarn/releases/yarn-4.12.0.cjs +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/.yarnrc.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/index.html +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/package.json +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/App.test.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/App.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/Auth.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/ErrorBoundary.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/ErrorDisplay.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/LoadingSpinner.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/RecentUploads.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/ResultsDisplay.test.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/ResultsSkeleton.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/UploadForm.test.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/components/UploadForm.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/hooks/useAnalysis.test.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/hooks/useAnalysis.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/hooks/useAuth.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/hooks/useBackendVersion.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/hooks/useRecentUploads.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/index.css +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/lib/supabase.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/main.tsx +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/src/types/api.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/vercel.json +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/vite.config.ts +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/frontend/yarn.lock +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/justfile +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/local_dev.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/mkdocs.yml +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/demos/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/demos/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/demos/api_demo.ipynb +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/demos/batch_processing_demo.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/demos/sample_data/.gitkeep +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/presentation_guide.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/revealjs/.gitignore +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/revealjs/Makefile +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/revealjs/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/revealjs/slides.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/presentation/speaker_script.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/requirements-docs.txt +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/samples/cmjs/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/SCRIPTS_QUICKREF.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/analyze_determinism_variance.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/basic-memory-utils.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/debug_contact_states.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/debug_detection.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/find_unused_features.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/generate_test_data.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/optimize_detection_params.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/plot_cmj_velocities.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/plot_validation_results.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/plot_velocities.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/prepare_ground_truth.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/README.md +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/add-issue.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/batch-set-fields.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/helpers.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/list.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/set-field.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/set-status.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project/summary.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/project.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/setup-github-deploy.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/setup-google-oauth.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/setup-supabase-local.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/setup-supabase-production.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/test_acceleration_standing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/test_determinism.sh +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/test_drop_start_debug.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/scripts/validate_known_heights.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/api.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cli.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/analysis.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/api.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/cli.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/debug_overlay.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/joint_angles.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/kinematics.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/metrics_validator.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/cmj/validation_bounds.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/auto_tuning.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/cli_utils.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/debug_overlay_utils.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/determinism.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/experimental.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/filtering.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/formatting.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/metadata.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/pipeline_utils.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/pose.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/quality.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/smoothing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/timing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/validation.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/core/video_io.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/analysis.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/api.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/cli.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/debug_overlay.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/kinematics.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/metrics_validator.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/dropjump/validation_bounds.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/src/kinemotion/py.typed +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cli/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cli/test_cmj.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cli/test_dropjump.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cli/test_imports.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_analysis.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_api.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_cli.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_joint_angles.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_kinematics.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/cmj/test_physiological_bounds.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/conftest.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_auto_tuning.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_cli_utils.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_filtering.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_formatting.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_metadata.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_pipeline_utils.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_pose.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_quality.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_smoothing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_timing.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_validation.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/core/test_video_io.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/__init__.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_adaptive_threshold.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_analysis.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_api.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_cli.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_contact_detection.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_kinematics.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_physiological_bounds.py +0 -0
- {kinemotion-0.48.0 → kinemotion-0.49.0}/tests/dropjump/test_validation_integration.py +0 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Feature Request System Configuration
|
|
3
|
+
type: note
|
|
4
|
+
permalink: development/feature-request-system-configuration
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Feature Request & Feedback System Configuration
|
|
8
|
+
|
|
9
|
+
## Frontend Configuration
|
|
10
|
+
|
|
11
|
+
### External Links Setup
|
|
12
|
+
Edit `frontend/src/config/links.ts`:
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
export const EXTERNAL_LINKS = {
|
|
16
|
+
// Replace with actual Google Forms URL
|
|
17
|
+
FEATURE_REQUEST: 'https://docs.google.com/forms/d/e/YOUR_FORM_ID/viewform',
|
|
18
|
+
GITHUB_ISSUES: 'https://github.com/feniix/kinemotion/issues',
|
|
19
|
+
DOCUMENTATION: 'https://github.com/feniix/kinemotion#readme',
|
|
20
|
+
} as const
|
|
21
|
+
|
|
22
|
+
export const UI_CONFIG = {
|
|
23
|
+
FEATURE_REQUEST: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
buttonText: 'Request Feature',
|
|
26
|
+
buttonIcon: '💡',
|
|
27
|
+
tooltip: 'Share your ideas and suggestions for improving Kinemotion',
|
|
28
|
+
openInNewTab: true,
|
|
29
|
+
},
|
|
30
|
+
} as const
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Google Forms Setup
|
|
34
|
+
|
|
35
|
+
1. Create form at [Google Forms](https://forms.google.com)
|
|
36
|
+
2. Include fields:
|
|
37
|
+
- Feature category (Analysis, UI, Performance, etc.)
|
|
38
|
+
- Feature description
|
|
39
|
+
- Use case/priority
|
|
40
|
+
- Additional comments
|
|
41
|
+
3. Get form URL and update FEATURE_REQUEST constant
|
|
42
|
+
|
|
43
|
+
## Component Usage
|
|
44
|
+
|
|
45
|
+
### FeatureRequestButton Props
|
|
46
|
+
```typescript
|
|
47
|
+
<FeatureRequestButton
|
|
48
|
+
variant="primary" // or "secondary"
|
|
49
|
+
size="medium" // "small", "medium", "large"
|
|
50
|
+
showIcon={true}
|
|
51
|
+
className="custom-class"
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Button Styles
|
|
56
|
+
- **Primary**: Blue background (`#6366f1`), white text
|
|
57
|
+
- **Secondary**: Light gray background (`#f3f4f6`), dark text
|
|
58
|
+
- **Sizes**: Small (0.75rem font), Medium (0.875rem), Large (1rem font)
|
|
59
|
+
|
|
60
|
+
## Database Detection
|
|
61
|
+
|
|
62
|
+
The frontend automatically detects backend database connectivity:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const { status: dbStatus, loading: dbLoading } = useDatabaseStatus()
|
|
66
|
+
|
|
67
|
+
// Conditional UI rendering
|
|
68
|
+
{dbStatus?.database_connected && (
|
|
69
|
+
<button>Add Coach Feedback</button>
|
|
70
|
+
)}
|
|
71
|
+
|
|
72
|
+
{!dbStatus?.database_connected && (
|
|
73
|
+
<span>Database Offline - Feedback Unavailable</span>
|
|
74
|
+
)}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Files Created
|
|
78
|
+
- `frontend/src/components/FeatureRequestButton.tsx`
|
|
79
|
+
- `frontend/src/components/FeedbackForm.tsx`
|
|
80
|
+
- `frontend/src/hooks/useDatabaseStatus.ts`
|
|
81
|
+
- `frontend/src/config/links.ts`
|
|
82
|
+
|
|
83
|
+
## Integration Points
|
|
84
|
+
- **ResultsDisplay**: Dedicated feedback section
|
|
85
|
+
- **Health Check**: Database status in `/health` endpoint
|
|
86
|
+
- **Analytics**: Google Analytics tracking included
|
|
87
|
+
|
|
88
|
+
## User Flow
|
|
89
|
+
1. Analysis completes → Results display
|
|
90
|
+
2. "Share Your Feedback" section appears
|
|
91
|
+
3. Options based on database status:
|
|
92
|
+
- Database connected: Coach feedback + feature request + report issue
|
|
93
|
+
- Database offline: Feature request + report issue + error message
|
|
94
|
+
4. Feature request opens Google Forms in new tab
|
|
95
|
+
5. Coach feedback saves to Supabase (if connected)
|
|
96
|
+
|
|
97
|
+
This system provides comprehensive user feedback collection while maintaining a seamless experience.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Supabase Database Integration Setup
|
|
3
|
+
type: note
|
|
4
|
+
permalink: development/supabase-database-integration-setup
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Supabase Database Integration for Coach Feedback
|
|
8
|
+
|
|
9
|
+
## Database Schema
|
|
10
|
+
|
|
11
|
+
Run this SQL in Supabase SQL Editor to create the required tables:
|
|
12
|
+
|
|
13
|
+
```sql
|
|
14
|
+
-- Analysis Sessions Table
|
|
15
|
+
CREATE TABLE IF NOT EXISTS analysis_sessions (
|
|
16
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
17
|
+
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
18
|
+
jump_type VARCHAR(50) NOT NULL CHECK (jump_type IN ('cmj', 'drop_jump')),
|
|
19
|
+
quality_preset VARCHAR(20) NOT NULL CHECK (quality_preset IN ('fast', 'balanced', 'accurate')),
|
|
20
|
+
original_video_url TEXT,
|
|
21
|
+
debug_video_url TEXT,
|
|
22
|
+
results_json_url TEXT,
|
|
23
|
+
analysis_data JSONB NOT NULL,
|
|
24
|
+
processing_time_s FLOAT,
|
|
25
|
+
upload_id VARCHAR(50),
|
|
26
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
27
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
-- Coach Feedback Table
|
|
31
|
+
CREATE TABLE IF NOT EXISTS coach_feedback (
|
|
32
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
33
|
+
analysis_session_id UUID NOT NULL REFERENCES analysis_sessions(id) ON DELETE CASCADE,
|
|
34
|
+
coach_user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
35
|
+
notes TEXT,
|
|
36
|
+
rating INTEGER CHECK (rating >= 1 AND rating <= 5),
|
|
37
|
+
tags TEXT[] DEFAULT '{}',
|
|
38
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
39
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
-- Indexes and RLS policies included in full schema
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Backend Integration
|
|
46
|
+
|
|
47
|
+
### New Files Created:
|
|
48
|
+
- `backend/src/kinemotion_backend/database.py` - Async Supabase client
|
|
49
|
+
- `backend/src/kinemotion_backend/analysis_api.py` - Feedback API endpoints
|
|
50
|
+
- `backend/src/kinemotion_backend/models.py` - Pydantic models
|
|
51
|
+
- `backend/supabase-schema.sql` - Complete database schema
|
|
52
|
+
|
|
53
|
+
### API Endpoints:
|
|
54
|
+
- `POST /api/analysis/sessions` - Create analysis sessions
|
|
55
|
+
- `GET /api/analysis/sessions` - List user sessions
|
|
56
|
+
- `GET /api/analysis/sessions/{id}` - Get session with feedback
|
|
57
|
+
- `POST /api/analysis/sessions/{id}/feedback` - Add coach feedback
|
|
58
|
+
- `GET /api/analysis/database-status` - Check database connection
|
|
59
|
+
|
|
60
|
+
### Key Features:
|
|
61
|
+
- Optional authentication (works with/without user login)
|
|
62
|
+
- JSONB storage for flexible analysis data querying
|
|
63
|
+
- Row Level Security for data privacy
|
|
64
|
+
- Async database operations
|
|
65
|
+
- Graceful error handling
|
|
66
|
+
|
|
67
|
+
## Frontend Integration
|
|
68
|
+
|
|
69
|
+
### Components Added:
|
|
70
|
+
- `FeedbackForm.tsx` - Modal feedback form with rating, tags, notes
|
|
71
|
+
- `FeatureRequestButton.tsx` - Reusable feature request button
|
|
72
|
+
- `useDatabaseStatus.ts` - Hook for checking database connectivity
|
|
73
|
+
|
|
74
|
+
### Configuration:
|
|
75
|
+
- `config/links.ts` - External links and UI settings
|
|
76
|
+
- Google Forms integration for feature requests
|
|
77
|
+
- Conditional UI based on database status
|
|
78
|
+
|
|
79
|
+
### User Experience:
|
|
80
|
+
- Smart feedback section with multiple options
|
|
81
|
+
- Database connection detection
|
|
82
|
+
- Responsive design
|
|
83
|
+
- Analytics tracking ready
|
|
84
|
+
|
|
85
|
+
## Setup Requirements:
|
|
86
|
+
1. Run database schema in Supabase
|
|
87
|
+
2. Configure SUPABASE_URL and SUPABASE_ANON_KEY
|
|
88
|
+
3. Update Google Forms URL in frontend config
|
|
89
|
+
4. Test integration with authenticated/unauthenticated users
|
|
90
|
+
|
|
91
|
+
## Example Queries:
|
|
92
|
+
```sql
|
|
93
|
+
-- Average jump height by user
|
|
94
|
+
SELECT user_id, AVG((analysis_data->'data'->>'jump_height')::float) as avg_jump_height
|
|
95
|
+
FROM analysis_sessions WHERE jump_type = 'cmj' GROUP BY user_id;
|
|
96
|
+
|
|
97
|
+
-- Sessions with feedback
|
|
98
|
+
SELECT s.*, f.rating, f.notes
|
|
99
|
+
FROM analysis_sessions s
|
|
100
|
+
LEFT JOIN coach_feedback f ON s.id = f.analysis_session_id
|
|
101
|
+
WHERE f.id IS NOT NULL;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This system enables comprehensive coach feedback collection and athlete performance tracking.
|
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
<!-- version list -->
|
|
9
9
|
|
|
10
|
+
## v0.49.0 (2025-12-13)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Normalize timing log event names to proper snake_case keys
|
|
15
|
+
([`ecbb154`](https://github.com/feniix/kinemotion/commit/ecbb154dc19f2de47c10bea9f638b13eb71026b4))
|
|
16
|
+
|
|
17
|
+
### Chores
|
|
18
|
+
|
|
19
|
+
- Update sonar app version
|
|
20
|
+
([`2975f7b`](https://github.com/feniix/kinemotion/commit/2975f7bf0ab4732ca92f7c9728ed3d8911992ca1))
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
- Implement comprehensive feedback system with Supabase database integration
|
|
25
|
+
([`9bcf73f`](https://github.com/feniix/kinemotion/commit/9bcf73f79436e2b4de900b58f95258719fcdce80))
|
|
26
|
+
|
|
27
|
+
|
|
10
28
|
## v0.48.0 (2025-12-12)
|
|
11
29
|
|
|
12
30
|
### Chores
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kinemotion
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.49.0
|
|
4
4
|
Summary: Video-based kinematic analysis for athletic performance
|
|
5
5
|
Project-URL: Homepage, https://github.com/feniix/kinemotion
|
|
6
6
|
Project-URL: Repository, https://github.com/feniix/kinemotion
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""API endpoints for analysis sessions and coach feedback."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
from fastapi import APIRouter, Depends, HTTPException, status
|
|
7
|
+
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
|
8
|
+
|
|
9
|
+
from kinemotion_backend.auth import SupabaseAuth
|
|
10
|
+
from kinemotion_backend.database import get_database_client
|
|
11
|
+
from kinemotion_backend.models import (
|
|
12
|
+
AnalysisSessionCreate,
|
|
13
|
+
AnalysisSessionResponse,
|
|
14
|
+
AnalysisSessionWithFeedback,
|
|
15
|
+
CoachFeedbackCreate,
|
|
16
|
+
CoachFeedbackResponse,
|
|
17
|
+
DatabaseError,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
logger = structlog.get_logger()
|
|
21
|
+
router = APIRouter(prefix="/api/analysis", tags=["Analysis"])
|
|
22
|
+
security = HTTPBearer()
|
|
23
|
+
auth = SupabaseAuth()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def get_current_user_id(
|
|
27
|
+
credentials: HTTPAuthorizationCredentials = Depends(security), # noqa: B008
|
|
28
|
+
) -> str:
|
|
29
|
+
"""Extract user ID from JWT token."""
|
|
30
|
+
try:
|
|
31
|
+
return auth.get_user_id(credentials.credentials)
|
|
32
|
+
except Exception as e:
|
|
33
|
+
logger.warning("user_authentication_failed", error=str(e))
|
|
34
|
+
raise HTTPException(
|
|
35
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
36
|
+
detail="Invalid authentication credentials",
|
|
37
|
+
) from e
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@router.post(
|
|
41
|
+
"/sessions",
|
|
42
|
+
response_model=AnalysisSessionResponse,
|
|
43
|
+
status_code=status.HTTP_201_CREATED,
|
|
44
|
+
responses={400: {"model": DatabaseError}, 500: {"model": DatabaseError}},
|
|
45
|
+
)
|
|
46
|
+
async def create_analysis_session(
|
|
47
|
+
session_data: AnalysisSessionCreate,
|
|
48
|
+
user_id: str = Depends(get_current_user_id),
|
|
49
|
+
) -> AnalysisSessionResponse:
|
|
50
|
+
"""Create a new analysis session record.
|
|
51
|
+
|
|
52
|
+
This endpoint stores analysis metadata and results in the database.
|
|
53
|
+
It's typically called after video analysis is completed.
|
|
54
|
+
"""
|
|
55
|
+
try:
|
|
56
|
+
db_client = get_database_client()
|
|
57
|
+
session_record = await db_client.create_analysis_session(
|
|
58
|
+
user_id=user_id,
|
|
59
|
+
jump_type=session_data.jump_type,
|
|
60
|
+
quality_preset=session_data.quality_preset,
|
|
61
|
+
analysis_data=session_data.analysis_data,
|
|
62
|
+
original_video_url=session_data.original_video_url,
|
|
63
|
+
debug_video_url=session_data.debug_video_url,
|
|
64
|
+
results_json_url=session_data.results_json_url,
|
|
65
|
+
processing_time_s=session_data.processing_time_s,
|
|
66
|
+
upload_id=session_data.upload_id,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logger.info(
|
|
70
|
+
"analysis_session_api_created",
|
|
71
|
+
session_id=session_record["id"],
|
|
72
|
+
user_id=user_id,
|
|
73
|
+
jump_type=session_data.jump_type,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
return AnalysisSessionResponse(**session_record)
|
|
77
|
+
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logger.error(
|
|
80
|
+
"create_analysis_session_api_error",
|
|
81
|
+
error=str(e),
|
|
82
|
+
user_id=user_id,
|
|
83
|
+
exc_info=True,
|
|
84
|
+
)
|
|
85
|
+
raise HTTPException(
|
|
86
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
87
|
+
detail=f"Failed to create analysis session: {str(e)}",
|
|
88
|
+
) from e
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@router.get(
|
|
92
|
+
"/sessions",
|
|
93
|
+
response_model=list[AnalysisSessionResponse],
|
|
94
|
+
responses={401: {"model": DatabaseError}, 500: {"model": DatabaseError}},
|
|
95
|
+
)
|
|
96
|
+
async def get_user_analysis_sessions(
|
|
97
|
+
limit: int = 50,
|
|
98
|
+
user_id: str = Depends(get_current_user_id),
|
|
99
|
+
) -> list[AnalysisSessionResponse]:
|
|
100
|
+
"""Get analysis sessions for the current user.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
limit: Maximum number of sessions to return (default: 50)
|
|
104
|
+
"""
|
|
105
|
+
try:
|
|
106
|
+
if limit <= 0 or limit > 100:
|
|
107
|
+
raise HTTPException(
|
|
108
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
109
|
+
detail="Limit must be between 1 and 100",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
db_client = get_database_client()
|
|
113
|
+
sessions = await db_client.get_user_analysis_sessions(
|
|
114
|
+
user_id=user_id, limit=limit
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
logger.info(
|
|
118
|
+
"user_analysis_sessions_api_retrieved",
|
|
119
|
+
user_id=user_id,
|
|
120
|
+
count=len(sessions),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
return [AnalysisSessionResponse(**session) for session in sessions]
|
|
124
|
+
|
|
125
|
+
except HTTPException:
|
|
126
|
+
raise
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.error(
|
|
129
|
+
"get_user_analysis_sessions_api_error",
|
|
130
|
+
error=str(e),
|
|
131
|
+
user_id=user_id,
|
|
132
|
+
exc_info=True,
|
|
133
|
+
)
|
|
134
|
+
raise HTTPException(
|
|
135
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
136
|
+
detail=f"Failed to retrieve analysis sessions: {str(e)}",
|
|
137
|
+
) from e
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@router.get(
|
|
141
|
+
"/sessions/{session_id}",
|
|
142
|
+
response_model=AnalysisSessionWithFeedback,
|
|
143
|
+
responses={
|
|
144
|
+
401: {"model": DatabaseError},
|
|
145
|
+
404: {"model": DatabaseError},
|
|
146
|
+
500: {"model": DatabaseError},
|
|
147
|
+
},
|
|
148
|
+
)
|
|
149
|
+
async def get_analysis_session(
|
|
150
|
+
session_id: str,
|
|
151
|
+
user_id: str = Depends(get_current_user_id),
|
|
152
|
+
) -> AnalysisSessionWithFeedback:
|
|
153
|
+
"""Get a specific analysis session with feedback.
|
|
154
|
+
|
|
155
|
+
Users can only access their own analysis sessions.
|
|
156
|
+
"""
|
|
157
|
+
try:
|
|
158
|
+
db_client = get_database_client()
|
|
159
|
+
session = await db_client.get_analysis_session(
|
|
160
|
+
session_id=session_id, user_id=user_id
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if not session:
|
|
164
|
+
raise HTTPException(
|
|
165
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
166
|
+
detail="Analysis session not found",
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
# Get feedback for this session
|
|
170
|
+
feedback = await db_client.get_session_feedback(analysis_session_id=session_id)
|
|
171
|
+
|
|
172
|
+
logger.info(
|
|
173
|
+
"analysis_session_api_retrieved",
|
|
174
|
+
session_id=session_id,
|
|
175
|
+
user_id=user_id,
|
|
176
|
+
feedback_count=len(feedback),
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
session_with_feedback = AnalysisSessionWithFeedback(**session)
|
|
180
|
+
session_with_feedback.feedback = [
|
|
181
|
+
CoachFeedbackResponse(**fb) for fb in feedback
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
return session_with_feedback
|
|
185
|
+
|
|
186
|
+
except HTTPException:
|
|
187
|
+
raise
|
|
188
|
+
except Exception as e:
|
|
189
|
+
logger.error(
|
|
190
|
+
"get_analysis_session_api_error",
|
|
191
|
+
error=str(e),
|
|
192
|
+
session_id=session_id,
|
|
193
|
+
user_id=user_id,
|
|
194
|
+
exc_info=True,
|
|
195
|
+
)
|
|
196
|
+
raise HTTPException(
|
|
197
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
198
|
+
detail=f"Failed to retrieve analysis session: {str(e)}",
|
|
199
|
+
) from e
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@router.get(
|
|
203
|
+
"/database-status",
|
|
204
|
+
response_model=dict[str, Any],
|
|
205
|
+
responses={500: {"model": DatabaseError}},
|
|
206
|
+
)
|
|
207
|
+
async def get_database_status() -> dict[str, Any]:
|
|
208
|
+
"""Check if the database is connected and working."""
|
|
209
|
+
try:
|
|
210
|
+
db_client = get_database_client()
|
|
211
|
+
|
|
212
|
+
# Try a simple query to test the connection
|
|
213
|
+
# We'll test by trying to access the analysis_sessions table
|
|
214
|
+
db_client.client.table("analysis_sessions").select("id").limit(1).execute()
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
"database_connected": True,
|
|
218
|
+
"tables_exist": True,
|
|
219
|
+
"message": "Database connection successful",
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.error("database_status_check_failed", error=str(e), exc_info=True)
|
|
224
|
+
return {
|
|
225
|
+
"database_connected": False,
|
|
226
|
+
"tables_exist": False,
|
|
227
|
+
"message": f"Database connection failed: {str(e)}",
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@router.post(
|
|
232
|
+
"/sessions/{session_id}/feedback",
|
|
233
|
+
response_model=CoachFeedbackResponse,
|
|
234
|
+
status_code=status.HTTP_201_CREATED,
|
|
235
|
+
responses={
|
|
236
|
+
400: {"model": DatabaseError},
|
|
237
|
+
401: {"model": DatabaseError},
|
|
238
|
+
404: {"model": DatabaseError},
|
|
239
|
+
500: {"model": DatabaseError},
|
|
240
|
+
},
|
|
241
|
+
)
|
|
242
|
+
async def create_coach_feedback(
|
|
243
|
+
session_id: str,
|
|
244
|
+
feedback_data: CoachFeedbackCreate,
|
|
245
|
+
coach_user_id: str = Depends(get_current_user_id),
|
|
246
|
+
) -> CoachFeedbackResponse:
|
|
247
|
+
"""Add coach feedback to an analysis session.
|
|
248
|
+
|
|
249
|
+
Any authenticated user can provide feedback on analysis sessions.
|
|
250
|
+
"""
|
|
251
|
+
try:
|
|
252
|
+
# Validate that the session exists
|
|
253
|
+
db_client = get_database_client()
|
|
254
|
+
session = await db_client.get_analysis_session(
|
|
255
|
+
session_id=session_id, user_id=coach_user_id
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
if not session:
|
|
259
|
+
# Try to get session without user restriction
|
|
260
|
+
# (coaches can provide feedback on any session)
|
|
261
|
+
# This would require modifying the database client
|
|
262
|
+
# to allow unrestricted access for feedback
|
|
263
|
+
# For now, we'll assume users can only provide feedback
|
|
264
|
+
# on their own sessions
|
|
265
|
+
raise HTTPException(
|
|
266
|
+
status_code=status.HTTP_404_NOT_FOUND,
|
|
267
|
+
detail="Analysis session not found",
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Override the session_id from the URL to ensure consistency
|
|
271
|
+
feedback_data.analysis_session_id = session_id
|
|
272
|
+
|
|
273
|
+
feedback_record = await db_client.create_coach_feedback(
|
|
274
|
+
analysis_session_id=session_id,
|
|
275
|
+
coach_user_id=coach_user_id,
|
|
276
|
+
notes=feedback_data.notes,
|
|
277
|
+
rating=feedback_data.rating,
|
|
278
|
+
tags=feedback_data.tags,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
logger.info(
|
|
282
|
+
"coach_feedback_api_created",
|
|
283
|
+
feedback_id=feedback_record["id"],
|
|
284
|
+
session_id=session_id,
|
|
285
|
+
coach_user_id=coach_user_id,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
return CoachFeedbackResponse(**feedback_record)
|
|
289
|
+
|
|
290
|
+
except HTTPException:
|
|
291
|
+
raise
|
|
292
|
+
except Exception as e:
|
|
293
|
+
logger.error(
|
|
294
|
+
"create_coach_feedback_api_error",
|
|
295
|
+
error=str(e),
|
|
296
|
+
session_id=session_id,
|
|
297
|
+
coach_user_id=coach_user_id,
|
|
298
|
+
exc_info=True,
|
|
299
|
+
)
|
|
300
|
+
raise HTTPException(
|
|
301
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
302
|
+
detail=f"Failed to create coach feedback: {str(e)}",
|
|
303
|
+
) from e
|
|
@@ -4,6 +4,7 @@ Real metrics integration with Cloudflare R2 storage for video and results manage
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
+
import re
|
|
7
8
|
import tempfile
|
|
8
9
|
from contextlib import asynccontextmanager
|
|
9
10
|
from datetime import datetime, timezone
|
|
@@ -33,6 +34,8 @@ from kinemotion.core.timing import (
|
|
|
33
34
|
from slowapi import Limiter, _rate_limit_exceeded_handler
|
|
34
35
|
from slowapi.util import get_remote_address
|
|
35
36
|
|
|
37
|
+
from kinemotion_backend.analysis_api import router as analysis_router
|
|
38
|
+
from kinemotion_backend.database import get_database_client
|
|
36
39
|
from kinemotion_backend.logging_config import get_logger, setup_logging
|
|
37
40
|
from kinemotion_backend.middleware import RequestLoggingMiddleware
|
|
38
41
|
|
|
@@ -360,6 +363,8 @@ try:
|
|
|
360
363
|
except ValueError:
|
|
361
364
|
logger.warning("r2_storage_not_configured", message="R2 credentials not provided")
|
|
362
365
|
|
|
366
|
+
# Include analysis API router
|
|
367
|
+
app.include_router(analysis_router)
|
|
363
368
|
|
|
364
369
|
# ========== Helper Functions ==========
|
|
365
370
|
|
|
@@ -520,6 +525,18 @@ async def health_check() -> dict[str, Any]:
|
|
|
520
525
|
except Exception:
|
|
521
526
|
kinemotion_version = "unknown"
|
|
522
527
|
|
|
528
|
+
# Check database connection
|
|
529
|
+
database_connected = False
|
|
530
|
+
try:
|
|
531
|
+
from kinemotion_backend.database import get_database_client
|
|
532
|
+
|
|
533
|
+
db_client = get_database_client()
|
|
534
|
+
# Test database with a simple query
|
|
535
|
+
db_client.client.table("analysis_sessions").select("id").limit(1).execute()
|
|
536
|
+
database_connected = True
|
|
537
|
+
except Exception as db_error:
|
|
538
|
+
logger.warning("database_health_check_failed", error=str(db_error))
|
|
539
|
+
|
|
523
540
|
return {
|
|
524
541
|
"status": "ok",
|
|
525
542
|
"service": "kinemotion-backend",
|
|
@@ -528,6 +545,7 @@ async def health_check() -> dict[str, Any]:
|
|
|
528
545
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
529
546
|
"r2_configured": r2_client is not None,
|
|
530
547
|
"trackers_initialized": len(global_pose_trackers) > 0,
|
|
548
|
+
"database_connected": database_connected,
|
|
531
549
|
}
|
|
532
550
|
|
|
533
551
|
|
|
@@ -672,9 +690,10 @@ async def analyze_video(
|
|
|
672
690
|
and "timing_breakdown_ms" in metrics["metadata"]["processing"]
|
|
673
691
|
):
|
|
674
692
|
timing_breakdown = metrics["metadata"]["processing"]["timing_breakdown_ms"]
|
|
675
|
-
# Normalize keys
|
|
693
|
+
# Normalize keys: remove special chars, spaces → underscores, lowercase
|
|
676
694
|
normalized_timings = {
|
|
677
|
-
stage.lower().replace(" ", "_")
|
|
695
|
+
re.sub(r"[^\w\s]", "", stage).lower().replace(" ", "_")
|
|
696
|
+
+ "_ms": duration
|
|
678
697
|
for stage, duration in timing_breakdown.items()
|
|
679
698
|
}
|
|
680
699
|
# Log each timing stage as a separate event for granular monitoring
|
|
@@ -744,6 +763,51 @@ async def analyze_video(
|
|
|
744
763
|
)
|
|
745
764
|
processing_time = time.time() - start_time
|
|
746
765
|
|
|
766
|
+
# Optionally store analysis session in database if user is authenticated
|
|
767
|
+
user_id = None
|
|
768
|
+
try:
|
|
769
|
+
auth_header = request.headers.get("Authorization")
|
|
770
|
+
if auth_header and auth_header.startswith("Bearer "):
|
|
771
|
+
from kinemotion_backend.auth import SupabaseAuth
|
|
772
|
+
|
|
773
|
+
auth = SupabaseAuth()
|
|
774
|
+
token = auth_header.split(" ")[1]
|
|
775
|
+
user_id = auth.get_user_id(token)
|
|
776
|
+
logger.info("user_authenticated_for_analysis", user_id=user_id)
|
|
777
|
+
except Exception as e:
|
|
778
|
+
logger.info("analysis_save_no_auth", reason=str(e))
|
|
779
|
+
user_id = None
|
|
780
|
+
|
|
781
|
+
# Store in database if authenticated
|
|
782
|
+
session_id = None
|
|
783
|
+
if user_id:
|
|
784
|
+
try:
|
|
785
|
+
db_client = get_database_client()
|
|
786
|
+
session_record = await db_client.create_analysis_session(
|
|
787
|
+
user_id=user_id,
|
|
788
|
+
jump_type=jump_type,
|
|
789
|
+
quality_preset=quality,
|
|
790
|
+
analysis_data=metrics,
|
|
791
|
+
original_video_url=original_video_url,
|
|
792
|
+
debug_video_url=debug_video_url,
|
|
793
|
+
results_json_url=results_url,
|
|
794
|
+
processing_time_s=processing_time,
|
|
795
|
+
upload_id=upload_id,
|
|
796
|
+
)
|
|
797
|
+
session_id = session_record["id"]
|
|
798
|
+
logger.info(
|
|
799
|
+
"analysis_session_saved",
|
|
800
|
+
session_id=session_id,
|
|
801
|
+
user_id=user_id,
|
|
802
|
+
)
|
|
803
|
+
except Exception as e:
|
|
804
|
+
# Log error but don't fail the analysis - this is optional storage
|
|
805
|
+
logger.warning(
|
|
806
|
+
"analysis_session_save_failed",
|
|
807
|
+
error=str(e),
|
|
808
|
+
user_id=user_id,
|
|
809
|
+
)
|
|
810
|
+
|
|
747
811
|
# Build successful response
|
|
748
812
|
jump_type_display = "drop_jump" if jump_type == "drop_jump" else "cmj"
|
|
749
813
|
response = AnalysisResponse(
|