import 'dart:convert'; import 'package:sendtrain/daos/actions_dao.dart'; import 'package:sendtrain/database/database.dart'; import 'package:sendtrain/helpers/date_time_helpers.dart'; class ActionModel { final ActionsDao dao; List items; Action action; ActionModel({required this.action, required AppDatabase db}) : dao = ActionsDao(db), items = _generateItems(action); int get id => action.id; ActionStatus get status => action.status; Map get state => json.decode(action.state); List get sets => items.whereType().toList(); List get allItems => _flattenedItems(); int get totalTime { int time = 0; for (int i = 0; i < allItems.length; i++) { Item item = allItems[i]; time += item.time ?? 0; } return toSeconds(time); } List _flattenedItems() { List items = []; for (int i = 0; i < this.items.length; i++) { Item item = this.items[i]; if (item.runtimeType == Set) { Set setItem = item as Set; for (int j = 0; j < setItem.items.length; j++) { items.add(setItem.items[j]); } } else { items.add(item); } } return items; } static List _generateItems(Action action) { int totalItems = 0; int setItems = 0; List items = []; final List setReps = json.decode(action.totalReps); if (action.restBeforeSets != null) { items.add(Rest( id: totalItems, position: totalItems, action: action, time: action.restBeforeSets!, name: 'prepare')); } for (int i = 0; i < action.totalSets; i++) { final int totalReps; if (setReps.length == 1) { totalReps = setReps.first; } else { totalReps = setReps[i]; } totalItems += 1; items.add(Set( id: totalItems, setOrder: setItems++, position: totalItems, action: action, totalReps: totalReps)); if (action.restBetweenSets != null && i < action.totalSets - 1) { totalItems += 1; items.add(Rest( id: totalItems, position: totalItems, action: action, time: action.restBetweenSets!, name: 'rest')); } } if (action.restAfterSets != null && totalItems != items.length) { totalItems += 1; items.add(Rest( id: totalItems, position: totalItems, action: action, time: action.restAfterSets!, name: 'cooldown')); } return items; } Future updateStatus(ActionStatus status) async { Action newAction = action.copyWith(id: action.id, status: status); await dao.createOrUpdate(newAction.toCompanion(true)); action = newAction; return newAction; } Future updateState(String state) async { Action newAction = action.copyWith(id: action.id, state: state); await dao.createOrUpdate(newAction.toCompanion(true)); action = newAction; return newAction; } } class Item { final int id; final Action action; int position; List items = []; dynamic value; final String name; int? parentId; int? time; Item( {required this.id, required this.position, required this.action, this.parentId, this.time}) : name = action.title; RepType get valueType => action.repType; String get humanValueType => valueType == RepType.time ? 'seconds' : 'reps'; } class Set extends Item { final int totalReps; int? setOrder; Set( {required super.id, required super.action, required super.position, required this.totalReps, this.setOrder}) { items = _generateItems(action, id, totalReps); } int? get weightMultiplyer => action.setWeights != null ? json.decode(action.setWeights!)[id] : null; List get reps => items.whereType().toList(); static List _generateItems(action, id, totalReps) { List items = []; // add item for exercise int position = 0; if (action.repType == RepType.time) { for (int i = 0; i < totalReps; i++) { position = position > 0 ? position + 1 : position; // don't show a rest before first rep if (i > 0) { items.add(Rest( id: position, position: position, parentId: id, action: action, time: action.restBetweenReps, name: 'rest')); } items.add(Reps( id: ++position, position: position, parentId: id, action: action)); if (action.isAlternating) { items.add(Rest( id: ++position, position: position, parentId: id, action: action, time: action.restBetweenReps, name: 'alternate')); items.add(Reps( id: ++position, position: position, parentId: id, action: action)); } } } else { items.add(Reps(id: id, position: position, action: action)); if (action.isAlternating) { items.add(Rest( id: ++position, position: position, parentId: id, action: action, time: action.restBetweenReps, name: 'alternate')); items.add(Reps(id: id, position: ++position, action: action)); } } return items; } } class Reps extends Item { Reps( {required super.id, required super.position, required super.action, super.parentId}); @override dynamic get value => type == RepType.time ? time : count; RepType get type => action.repType; @override int? get time => toSeconds(action.repLength!); int? get count => getReps(id, json.decode(action.totalReps)); int? get weight => action.repWeights != null ? json.decode(action.repWeights!)[id] : null; static int getReps(setId, reps) { if (reps.length > 1) { return reps[setId]; } else { return reps.first; } } } class Rest extends Item { @override String name; Rest( {required super.id, required super.position, required super.action, super.parentId, required super.time, required this.name}); // @override // String get name => 'Rest'; @override int get value => toSeconds(time ?? 0); @override RepType get valueType => RepType.time; }