Technical Documentation

Comprehensive technical guide for developers contributing to or learning from SYHA Forge.

Technology Stack

Framework

Flutter 3.6.2+ - Cross-platform mobile development framework using Dart

Backend

Firebase - Authentication, Cloud Firestore for data storage

State Management

Provider 6.0.5 - Reactive state management and dependency injection

Local Storage

SharedPreferences 2.2.2 - Persistent key-value storage for offline data

Charts

FL Chart 0.69.2 - Beautiful, customizable charts for progress visualization

Calendar

Table Calendar 3.0.9 - Highly customizable calendar widget

Architecture

SYHA Forge follows a clean architecture pattern with clear separation of concerns.

Directory Structure

lib/
├── constants/          # App-wide constants
│   ├── app_colors.dart      # Color definitions
│   ├── app_strings.dart     # Localized strings
│   └── app_text_styles.dart # Text styling
├── models/             # Data models
│   ├── exercise.dart        # Exercise entity
│   ├── workout.dart         # Workout program
│   ├── workout_history.dart # Completed workout records
│   ├── chart_data.dart      # Chart data structures
│   └── user.dart            # User profile model
├── screens/            # UI screens
│   ├── home_screen.dart
│   ├── profile_screen.dart
│   ├── programs_screen.dart
│   ├── full_calendar_screen.dart
│   ├── progress_charts_screen.dart
│   └── ...
├── services/           # Business logic
│   ├── data_manager.dart              # Central data management
│   ├── progress_analytics_service.dart # Progress calculations
│   ├── muscle_recovery_tracker.dart   # Muscle group recovery tracking
│   ├── workout_recommendation_service.dart # Smart workout recommendations
│   ├── profile_service.dart           # User profile management
│   ├── auth_service.dart              # Firebase authentication
│   └── theme_service.dart             # Theme customization
├── widgets/            # Reusable UI components
│   ├── muscle_recovery_card.dart      # Recovery status display
│   └── compact_calendar.dart          # Week-view calendar
└── main.dart           # App entry point

Layer Responsibilities

Data Flow

State Management

SYHA Forge uses Provider for reactive state management:

// Service definition
class DataManager extends ChangeNotifier {
  List _workouts = [];

  void addWorkout(Workout workout) {
    _workouts.add(workout);
    notifyListeners(); // Triggers UI rebuild
  }
}

// Provider setup in main.dart
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => DataManager()),
    ChangeNotifierProvider(create: (_) => ProfileService()),
    // ... other providers
  ],
  child: MyApp(),
)

// Consumption in screens
final dataManager = Provider.of(context);
// OR
Consumer(
  builder: (context, dataManager, child) => ...
)

Data Persistence

Data is persisted using a hybrid approach:

Key Services

DataManager

Central hub for all workout-related data. Implements the Singleton pattern.

class DataManager extends ChangeNotifier {
  static final DataManager _instance = DataManager._internal();
  factory DataManager() => _instance;

  List _exercises = [];
  List _workouts = [];
  List _workoutHistory = [];

  // CRUD operations with automatic persistence
  void addWorkout(Workout workout) { ... }
  void updateWorkout(int index, Workout workout) { ... }
  void removeWorkout(int index) { ... }

  // Query methods
  List getWorkoutHistoryForDate(DateTime date) { ... }
  bool hasWorkoutOnDate(DateTime date) { ... }
  int workoutsThisMonth([DateTime? forDate]) { ... }
}

ProgressAnalyticsService

Stateless service that performs all analytics calculations. See Formulas page for detailed explanations.

class ProgressAnalyticsService {
  // Analyzes overall strength across all exercises
  OverallStrengthData analyzeOverallStrength(
    List histories,
    {int lookbackDays = 90}
  ) { ... }

  // Tracks individual exercise progress
  ExerciseProgressData analyzeExerciseProgress(
    String exerciseId,
    String exerciseName,
    List histories,
    {int lookbackDays = 90}
  ) { ... }

  // Additional analytics methods...
}

ProfileService

Manages user profile data including body weight history.

class ProfileService extends ChangeNotifier {
  double? _weightKg;
  List _weightHistory = [];

  Future setWeightKg(double? kg) async {
    _weightKg = kg;
    // Auto-save to weight history
    final entry = ChartDataPoint(
      date: DateTime.now(),
      value: kg
    );
    _weightHistory.insert(0, entry);
    // Persist to SharedPreferences
    await _saveToStorage();
    notifyListeners();
  }
}

MuscleRecoveryTracker

Tracks muscle group recovery status and calculates training readiness. Uses optimal recovery days per muscle group to determine which muscles are ready to train. See Muscle Recovery Formulas for details.

class MuscleRecoveryTracker {
  // Optimal recovery days per muscle group (legs: 3, chest: 2, forearms: 1, etc.)
  static const Map<MuscleGroup, int> _optimalRecoveryDays = { ... };

  // Scans all workout history, cross-referencing old exercises
  // with current muscle group assignments
  Map<MuscleGroup, int> calculateDaysSinceLastTraining(
    List<WorkoutHistory> histories,
    {Map<String, Exercise>? currentExercises}
  ) { ... }

  // Converts days-since-training into 0.0-1.5 priority score
  Map<MuscleGroup, double> calculateRecoveryPriority(
    Map<MuscleGroup, int> daysSinceTraining
  ) { ... }

  // Returns muscles with priority >= 0.7 (ready to train)
  List<MuscleGroup> getMusclesToTrain(...) { ... }

  // Returns muscles with priority < 0.3 (need rest)
  List<MuscleGroup> getMusclesToRest(...) { ... }
}

WorkoutRecommendationService

Generates daily workout recommendations by combining muscle recovery data, wellness status, and training history. Passes current exercise definitions to the recovery tracker to ensure old history entries without muscle groups are properly accounted for.

class WorkoutRecommendationService extends ChangeNotifier {
  final MuscleRecoveryTracker _recoveryTracker;
  final DataManager _dataManager;

  // Builds exercise ID -> Exercise map for cross-referencing
  Map<String, Exercise> _buildCurrentExercisesMap() {
    return {for (var e in _dataManager.exercises) e.id: e};
  }

  // All public methods pass currentExercises to the tracker
  Map<MuscleGroup, int> getDaysSinceLastTraining() { ... }
  Map<MuscleGroup, double> getMuscleRecoveryPriorities() { ... }

  // Analyzes wellness, recovery, history to recommend workout
  Future<WorkoutRecommendation?> generateTodaysRecommendation() { ... }
}

Visual Indicators System

Forge uses color-coded visual indicators to provide instant feedback on exercise performance and completion.

Program View - Completion Status

When viewing a program's exercise list (programs_screen.dart), each exercise is checked against the last completed session:

// Find last session for this workout
final lastSession = _findLastSessionForWorkout(dataManager, workout.id);
final completedExerciseIds = lastSession.exerciseResults
    .map((r) => r.exercise.id).toSet();

// For each exercise in the program
final wasCompleted = completedExerciseIds.contains(exercise.id);
// Color: wasCompleted ? programColor : AppColors.error

Calendar View - Rep Regression

When viewing expanded workout details in the calendar (full_calendar_screen.dart), exercises are compared against the previous session of the same workout:

// Compare total reps against previous session
final currentTotalReps = result.setResults.fold(0, (sum, s) => sum + s.actualReps);
final prevReps = previousSessionReps[exercise.id];
final isRegression = prevReps != null && currentTotalReps < prevReps;

Data Models

Exercise Model

class Exercise {
  final String id;
  final String name;
  final String description;
  final ExerciseDifficulty difficulty;
  final List muscleGroups;
  final DateTime createdAt;

  // JSON serialization
  Map toJson() { ... }
  factory Exercise.fromJson(Map json) { ... }
}

Workout Model

class Workout {
  final String id;
  final String name;
  final List exercises;
  final DateTime createdAt;
}

class WorkoutExercise {
  final Exercise exercise;
  final int sets;
  final int targetReps;
  final double weight;
  final Exercise? alternativeExercise;
}

WorkoutHistory Model

class WorkoutHistory {
  final String id;
  final DateTime date;
  final WorkoutSession session;

  // Computed property for date-only comparisons
  DateTime get dateOnly => DateTime(
    date.year,
    date.month,
    date.day,
  );
}

class WorkoutSession {
  final String workoutId;
  final String workoutName;
  final List exerciseResults;
  final int totalDurationSeconds;
}

UI Patterns

Theme System

SYHA Forge uses a dynamic theme system with user-customizable colors:

// AppColor provider for dynamic theming
class AppColor extends ChangeNotifier {
  Color _color = AppColors.primary;

  Color get color => _color;

  void setColor(Color color) {
    _color = color;
    notifyListeners();
  }
}

// Usage in widgets
Consumer(
  builder: (context, appColor, _) => Container(
    color: appColor.color,
    child: ...
  ),
)

Responsive Design

All screens adapt to different screen sizes using MediaQuery:

// Example from calendar screen
padding: EdgeInsets.fromLTRB(16, 16, 16, 100), // Extra bottom padding

// Dialog constraints
ConstrainedBox(
  constraints: BoxConstraints(
    maxHeight: MediaQuery.of(context).size.height * 0.7,
  ),
  child: ...
)

Custom Widgets

Reusable card components throughout the app:

Widget _buildStatCard(String label, String value, IconData icon) {
  return Card(
    elevation: 2,
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        children: [
          Icon(icon, color: AppColors.primary),
          Text(value, style: AppTextStyles.h3),
          Text(label, style: AppTextStyles.caption),
        ],
      ),
    ),
  );
}

Firebase Integration

Authentication

class AuthService extends ChangeNotifier {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  Future signInWithEmail(String email, String password) async {
    final credential = await _auth.signInWithEmailAndPassword(
      email: email,
      password: password,
    );
    return credential.user;
  }

  Future signOut() async {
    await _auth.signOut();
    notifyListeners();
  }
}

Firestore Data Model

// User collection
users/{userId}/
  - name: string
  - email: string
  - createdAt: timestamp
  - profile: {
      weightKg: number
      goals: array
      experienceLevel: string
    }

// Leaderboards collection
leaderboards/powerlifting/
  - entries: array of {userId, totalKg, date}
leaderboards/streetlifting/
  - entries: array of {userId, score, date}

Performance Optimizations

Example: Deduplication Logic

// DataManager prevents duplicate workout history entries
final seen = {};
_workoutHistory = [];
for (var history in loadedHistory) {
  final dateKey = history.dateOnly.toIso8601String();
  final workoutKey = history.session.workoutName;
  final uniqueKey = '$dateKey-$workoutKey-${history.session.exerciseResults.length}';

  if (!seen.contains(uniqueKey)) {
    seen.add(uniqueKey);
    _workoutHistory.add(history);
  }
}

Testing

Unit Tests

Service logic should be tested with unit tests:

// Example test for ProgressAnalyticsService
test('calculates strength coefficient correctly', () {
  final histories = [
    // Create test workout histories
  ];
  final service = ProgressAnalyticsService();
  final result = service.analyzeOverallStrength(histories);

  expect(result.currentTotalStrength, closeTo(150.0, 0.1));
});

Widget Tests

Screen components should have widget tests:

testWidgets('displays workout cards', (tester) async {
  await tester.pumpWidget(
    MaterialApp(home: FullCalendarScreen()),
  );

  expect(find.text('Workout Calendar'), findsOneWidget);
});

Security Considerations

Localization

SYHA Forge uses Flutter's built-in localization system:

// l10n.yaml configuration
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

// Usage in code
final l10n = AppLocalizations.of(context)!;
Text(l10n.workoutName); // Automatically localized

Currently supported languages: English (more coming soon!)

Building & Deployment

Development Build

# Run in debug mode
flutter run

# Run with specific device
flutter run -d [device-id]

Production Build

# Android APK
flutter build apk --release

# Android App Bundle (for Play Store)
flutter build appbundle --release

# iOS
flutter build ios --release

Version Management

Version is defined in pubspec.yaml:

version: 1.0.0+1
# Format: major.minor.patch+buildNumber

Future Improvements