/* * This file is part of wger Workout Manager . * Copyright (C) 2020 wger Team * * wger Workout Manager is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wger Workout Manager is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import 'package:json_annotation/json_annotation.dart'; import 'package:wger/helpers/date.dart'; import 'package:wger/helpers/json.dart'; import 'package:wger/models/workouts/day.dart'; import 'package:wger/models/workouts/day_data.dart'; import 'package:wger/models/workouts/log.dart'; import 'package:wger/models/workouts/session_api.dart'; part 'routine.g.dart'; @JsonSerializable() class Routine { static const MIN_LENGTH_DESCRIPTION = 0; static const MAX_LENGTH_DESCRIPTION = 1000; static const MIN_LENGTH_NAME = 3; static const MAX_LENGTH_NAME = 25; /// In weeks static const MIN_DURATION = 2; static const MAX_DURATION = 16; static const DEFAULT_DURATION = 12; @JsonKey(required: true, includeToJson: false) int? id; @JsonKey(required: true, toJson: dateToUtcIso8601) late DateTime created; @JsonKey(required: true, name: 'name') late String name; @JsonKey(required: true, name: 'description') late String description; @JsonKey(required: true, name: 'fit_in_week') late bool fitInWeek; @JsonKey(required: true, toJson: dateToYYYYMMDD) late DateTime start; @JsonKey(required: true, toJson: dateToYYYYMMDD) late DateTime end; @JsonKey(includeFromJson: true, required: false, includeToJson: false) List days = []; @JsonKey(includeFromJson: false, includeToJson: false) List dayData = []; @JsonKey(includeFromJson: false, includeToJson: false) List dayDataGym = []; @JsonKey(required: false, includeToJson: false, defaultValue: []) List sessions = []; Routine({ this.id, DateTime? created, required this.name, DateTime? start, DateTime? end, this.fitInWeek = false, String? description, this.days = const [], this.dayData = const [], this.dayDataGym = const [], this.sessions = const [], }) { this.created = created ?? DateTime.now(); this.start = start ?? DateTime.now(); this.end = end ?? DateTime.now().add(const Duration(days: DEFAULT_DURATION * 7)); this.description = description ?? ''; } Routine.empty() { name = ''; description = ''; created = DateTime.now(); start = DateTime.now(); end = DateTime.now().add(const Duration(days: DEFAULT_DURATION * 7)); fitInWeek = true; } // Boilerplate factory Routine.fromJson(Map json) => _$RoutineFromJson(json); Map toJson() => _$RoutineToJson(this); List get logs { final out = []; for (final session in sessions) { out.addAll(session.logs); } return out; } int? getIteration({DateTime? date}) { date ??= DateTime.now(); for (final data in dayData) { if (data.date.isSameDayAs(date)) { return data.iteration; } } return null; } List get dayDataCurrentIteration { final iteration = getIteration(date: DateTime.now()) ?? 1; return dayData.where((data) => data.iteration == iteration).toList(); } List get dayDataCurrentIterationGym { final iteration = getIteration(date: DateTime.now()) ?? 1; return dayDataGym.where((data) => data.iteration == iteration).toList(); } /// Filters the workout logs by exercise and sorts them by date /// /// Optionally, filters list so that only unique logs are returned. "Unique" /// means here that the values are the same, i.e. logs with the same weight, /// reps, etc. are considered equal. Workout ID, Log ID and date are not /// considered. List filterLogsByExercise(int exerciseId, {bool unique = false}) { var out = logs.where((log) => log.exerciseId == exerciseId).toList(); if (unique) { out = out.toSet().toList(); } out.sort((a, b) => b.date.compareTo(a.date)); return out; } /// Groups logs by repetition Map> groupLogsByRepetition({ List? logs, filterNullWeights = false, filterNullReps = false, }) { final workoutLogs = logs ?? this.logs; final Map> groupedLogs = {}; for (final log in workoutLogs) { if (log.repetitions == null || (filterNullWeights && log.weight == null) || (filterNullReps && log.repetitions == null)) { continue; } if (!groupedLogs.containsKey(log.repetitions)) { groupedLogs[log.repetitions!] = []; } groupedLogs[log.repetitions]!.add(log); } return groupedLogs; } }