new importation en fonction de la categorie et ready pour l'importation

pull/4/head
Enzo 2 years ago
parent 74661ea421
commit 8a92895371

@ -16,30 +16,32 @@ class ProfileInfoUser extends StatelessWidget {
subtitle: "Nombre d'activité", subtitle: "Nombre d'activité",
), ),
), ),
SizedBox( const SizedBox(
width: 15, width: 15,
), ),
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: "h/j", title: context.watch<User>().getTotalTimeAllActivity().toString(),
subtitle: "Temps en activité", subtitle: "Temps en activité",
), ),
), ),
SizedBox( const SizedBox(
width: 15, width: 15,
), ),
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: "+ m", title:
"${context.watch<User>().getTotalDenivelePositif().toString()} + m",
subtitle: "Total dénivelé positif", subtitle: "Total dénivelé positif",
), ),
), ),
SizedBox( const SizedBox(
width: 15, width: 15,
), ),
Expanded( Expanded(
child: TitleSubtitleCell( child: TitleSubtitleCell(
title: "- m", title:
"${context.watch<User>().getTotalDeniveleNegatif().toString()} - m",
subtitle: "Total dénivelé négatif", subtitle: "Total dénivelé négatif",
), ),
), ),

@ -16,6 +16,9 @@ class ActivityOfUser {
String get fileUuid => _fileUuid; String get fileUuid => _fileUuid;
String get nameFile => _nameFile; String get nameFile => _nameFile;
String get category => _categorie; String get category => _categorie;
double get time => _timeActivity;
double get denivelePos => _denivelePositif;
double get deniveleNeg => _deniveleNegatif;
Map<String, int> get enteteCSV => _enteteCSV; Map<String, int> get enteteCSV => _enteteCSV;
// -- Getter/Setter -- Ancien // // -- Getter/Setter -- Ancien //

@ -0,0 +1,15 @@
abstract class ActivityInfo {
// -- Time -- //
String startTime = "2000-01-01";
double timeOfActivity = 0.0;
// -- BPM -- //
int bpmMax = 0;
int bpmMin = 300;
int bpmAvg = 0;
// -- Fonction pour lire le csv et remplir la classe -- //
ActivityInfo getData(List<List<String>> csv);
String toJson();
}

@ -0,0 +1,41 @@
import 'dart:convert';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
class ActivityInfoGeneric implements ActivityInfo {
// ------- Ajout --------- //
// ------- Activity Info -------- //
@override
late int bpmAvg;
@override
late int bpmMax;
@override
late int bpmMin;
@override
late String startTime;
@override
late double timeOfActivity;
@override
ActivityInfo getData(List<List<String>> csv) {
return this;
}
@override
// Méthode pour convertir les attributs en JSON
String toJson() {
Map<String, dynamic> jsonMap = {
'bpmAvg': bpmAvg,
'bpmMax': bpmMax,
'bpmMin': bpmMin,
'startTime': startTime,
'timeOfActivity': timeOfActivity,
};
return jsonEncode(jsonMap);
}
}

@ -0,0 +1,48 @@
import 'dart:convert';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
class ActivityInfoWalking implements ActivityInfo {
// ------- Ajout --------- //
// -- Denivelé -- //
double denivelePositif = 0.0;
double deniveleNegatif = 0.0;
// ------- Activity Info -------- //
@override
int bpmAvg = 0;
@override
int bpmMax = 0;
@override
int bpmMin = 0;
@override
String startTime = "2000-01-01";
@override
double timeOfActivity = 0.0;
@override
ActivityInfo getData(List<List<String>> csv) {
for (int i = 0; i < csv.length; i++) {}
return this;
}
@override
// Méthode pour convertir les attributs en JSON
String toJson() {
Map<String, dynamic> jsonMap = {
'denivelePositif': denivelePositif,
'deniveleNegatif': deniveleNegatif,
'bpmAvg': bpmAvg,
'bpmMax': bpmMax,
'bpmMin': bpmMin,
'startTime': startTime,
'timeOfActivity': timeOfActivity,
};
return jsonEncode(jsonMap);
}
}

@ -32,6 +32,8 @@ class RequestApi extends IDataStrategy {
if ((response.statusCode == 404)) { if ((response.statusCode == 404)) {
return const Tuple2(false, "404 - NOT FOUND"); return const Tuple2(false, "404 - NOT FOUND");
} }
print(response.statusCode);
print(response.body);
return const Tuple2(false, "Fail"); return const Tuple2(false, "Fail");
} }

@ -1,11 +0,0 @@
class DataFile {
final List<List<String>> csvData;
final String category;
final String startTime;
final double denivelePositif;
final double deniveleNegatif;
final double timeOfActivity;
DataFile(this.csvData, this.category, this.startTime, this.denivelePositif,
this.deniveleNegatif, this.timeOfActivity);
}

@ -3,7 +3,10 @@ import 'dart:typed_data';
import 'package:csv/csv.dart'; import 'package:csv/csv.dart';
import 'package:fit_tool/fit_tool.dart'; import 'package:fit_tool/fit_tool.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:smartfit_app_mobile/modele/data_file.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info_generic.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info_walking.dart';
import 'package:tuple/tuple.dart';
class ManagerFile { class ManagerFile {
// -- Field // -- Field
@ -19,10 +22,10 @@ class ManagerFile {
final String _fieldTemperature = "temperature"; final String _fieldTemperature = "temperature";
// -- Not in CSV -- // // -- Not in CSV -- //
final String _session = "session"; static const String _session = "session";
final String _startTime = "start_time"; static const String _startTime = "start_time";
final String _sport = "sport"; static const String _sport = "sport";
final String _timeActivity = "total_elapsed_time"; static const String _timeActivity = "total_elapsed_time";
// -- Getter field // -- Getter field
String get fieldTimeStamp => _fieldTimestamp; String get fieldTimeStamp => _fieldTimestamp;
@ -36,7 +39,14 @@ class ManagerFile {
String get fieldTotalCalories => _fieldTotalCalorie; String get fieldTotalCalories => _fieldTotalCalorie;
String get fieldTemperature => _fieldTemperature; String get fieldTemperature => _fieldTemperature;
// -- Categorie -- //
static const String _generic = "generic";
static const String _velo = "cycling";
static const String _marche = "walking";
List<String> allowedFieldWalking = List.empty(growable: true); List<String> allowedFieldWalking = List.empty(growable: true);
List<String> allowedFieldGeneric = List.empty(growable: true);
List<String> allowedFieldCycling = List.empty(growable: true);
ManagerFile() { ManagerFile() {
allowedFieldWalking = [ allowedFieldWalking = [
@ -51,71 +61,125 @@ class ManagerFile {
_fieldTotalCalorie, _fieldTotalCalorie,
_fieldTemperature _fieldTemperature
]; ];
allowedFieldGeneric = [_fieldTimestamp, _fieldBPM];
allowedFieldCycling = [
_fieldTimestamp,
_fieldPositionLatitue,
_fieldPositionLongitude,
_fieldDistance,
_fieldBPM,
_fieldSpeed,
_fieldAltitude,
_fieldTotalCalorie,
_fieldTemperature
];
} }
DataFile convertBytesFitFileIntoCSVList(Uint8List bytes) { // -- Read the byte of file CSV -- //
FitFile fitFile = FitFile.fromBytes(bytes); List<List<dynamic>> convertByteIntoCSV(Uint8List bytes) {
return const CsvToListConverter().convert(utf8.decode(bytes));
}
// ----------- Lire le fit et extarire les données qu'on choisi ----------- // String _getCategoryById(int id) {
List<Map<String, Map<String, String>>> dataResult = switch (id) {
List.empty(growable: true); case 0:
// -- Start Time default -- // return _generic;
String startTime = "2000-01-01"; case 2:
// -- Category Default -- // return _velo;
String category = "Generic"; case 11:
// -- Time of activity default -- // return _marche;
double timeActivity = 0.0; default:
// -- Denivelé positif et négatif -- // return _generic;
double denivelePositif = 0.0; }
double deniveleNegatif = 0.0; }
double lastDenivele = 0.0;
// --------------------------------------- //
for (Record element in fitFile.records) {
List listeField = element.toRow();
Map<String, Map<String, String>> ligneDataResult = {};
// -- Skip ligne whith no data -- //
bool skip = true;
// -- Session -- //
bool sesssionLigne = false;
if (listeField[0] != "Data") { // ------------- Get The path of application --- //
continue; Future<String> get localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
} }
for (int i = 0; i < listeField.length;) { Tuple4<bool, List<List<String>>, ActivityInfo, String>
// -- Check si c'est une ligne session --// convertBytesFitFileIntoCSVListAndGetInfo(Uint8List bytes) {
if (i == 0 && listeField[2] == _session) { List<Record> fitFile = FitFile.fromBytes(bytes).records;
sesssionLigne = true; String categorie;
} List<String> fieldAllowed = [];
// -- Si ligne session && starttime -- // ActivityInfo info;
if (sesssionLigne && listeField[i] == _startTime) { // -- Chercher ligne session -- //
startTime = List<dynamic> ligneSession = _getLigneSession(fitFile);
DateTime.fromMillisecondsSinceEpoch(listeField[i + 1] as int) if (ligneSession.isEmpty) {
return Tuple4(false, List.empty(), ActivityInfoGeneric(), "");
}
categorie =
_getCategoryById(int.parse(_getXfromListe(_sport, ligneSession)));
// -- Si la catégorie est pas prévu est est généric -- //
switch (categorie) {
case (_marche):
fieldAllowed = allowedFieldWalking;
info = ActivityInfoWalking();
break;
case (_generic):
fieldAllowed = allowedFieldGeneric;
info = ActivityInfoGeneric();
break;
default:
// A REMETRE EN GENERIC
//fieldAllowed = allowedFieldGeneric;
//info = ActivityInfoGeneric();
//categorie = _generic;
fieldAllowed = allowedFieldWalking;
info = ActivityInfoWalking();
break;
}
List<List<String>> csvData = transformDataMapIntoCSV(
getDataOfListeOfRecord(fitFile, fieldAllowed), fieldAllowed);
// Remplir info avec la ligne session
info.startTime = DateTime.fromMillisecondsSinceEpoch(
int.parse(_getXfromListe(_startTime, ligneSession)))
.toIso8601String(); .toIso8601String();
}
// -- Si ligne session && sport -- // return Tuple4(true, csvData, info.getData(csvData), categorie);
if (sesssionLigne && listeField[i] == _sport) {
category = _getCategoryById(listeField[i + 1] as int);
} }
// -- Si ligne session && total_elapsed_time -- // List<dynamic> _getLigneSession(List<Record> listRecord) {
if (sesssionLigne && listeField[i] == _timeActivity) { for (int i = listRecord.length - 1; i != listRecord.length - 5; i--) {
timeActivity = listeField[i + 1]; List<dynamic> tmpListe = listRecord[i].toRow();
if (tmpListe[0] == "Data" && tmpListe[2] == _session) {
return tmpListe;
}
}
return List.empty();
} }
// Calcul denivelé positif et négatif String _getXfromListe(String x, List<dynamic> liste) {
if (listeField[i] == _fieldAltitude) { for (int i = 0; i < liste.length; i++) {
if (listeField[i + 1] > lastDenivele) { if (liste[i] == x) {
denivelePositif += listeField[i + 1] - lastDenivele; return liste[i + 1].toString();
} else { }
deniveleNegatif += (listeField[i + 1] - lastDenivele) * -1;
} }
lastDenivele = listeField[i + 1]; return "null";
} }
//------//
if (allowedFieldWalking.contains(listeField[i])) { List<Map<String, Map<String, String>>> getDataOfListeOfRecord(
List<Record> listeRecord, List<String> allowedField) {
List<Map<String, Map<String, String>>> dataResult =
List.empty(growable: true);
for (Record element in listeRecord) {
List listeField = element.toRow();
Map<String, Map<String, String>> ligneDataResult = {};
// -- Skip ligne whith no data -- //
bool skip = true;
// -- Si ce n'est pas de la data on pass -- //
if (listeField[0] != "Data") {
continue;
}
for (int i = 0; i < listeField.length;) {
if (allowedField.contains(listeField[i])) {
Map<String, String> tmp = {}; Map<String, String> tmp = {};
tmp["Value"] = listeField[i + 1].toString(); tmp["Value"] = listeField[i + 1].toString();
tmp["Unite"] = listeField[i + 2].toString(); tmp["Unite"] = listeField[i + 2].toString();
@ -123,27 +187,33 @@ class ManagerFile {
i += 2; i += 2;
skip = false; skip = false;
} }
// -- Pour boucler -- //
i += 1; i += 1;
} }
if (!skip) { if (!skip) {
dataResult.add(ligneDataResult); dataResult.add(ligneDataResult);
} }
} }
// -------- FIN ---------- // return dataResult;
}
List<List<String>> transformDataMapIntoCSV(
List<Map<String, Map<String, String>>> listeMap,
List<String> fieldAllowed) {
// ------- Création du csv ----- // // ------- Création du csv ----- //
// --- Création de l'entête -- // // --- Création de l'entête -- //
List<String> enteteCSV = []; List<String> enteteCSV = [];
for (String field in allowedFieldWalking) { for (String field in fieldAllowed) {
enteteCSV.add("Value_$field"); enteteCSV.add("Value_$field");
enteteCSV.add("Unite_$field"); enteteCSV.add("Unite_$field");
} }
List<List<String>> csvData = List.empty(growable: true); List<List<String>> csvData = List.empty(growable: true);
// //
for (Map<String, Map<String, String>> ligne in dataResult) { for (Map<String, Map<String, String>> ligne in listeMap) {
List<String> tmpLigne = List.empty(growable: true); List<String> tmpLigne = List.empty(growable: true);
for (String field in allowedFieldWalking) { for (String field in fieldAllowed) {
if (!ligne.containsKey(field)) { if (!ligne.containsKey(field)) {
tmpLigne.add("null"); tmpLigne.add("null");
tmpLigne.add("null"); tmpLigne.add("null");
@ -156,97 +226,6 @@ class ManagerFile {
} }
csvData.insert(0, enteteCSV); csvData.insert(0, enteteCSV);
// ------- FIN --------------- // // ------- FIN --------------- //
return DataFile(csvData, category, startTime, denivelePositif, return csvData;
deniveleNegatif, timeActivity);
} }
// -- Read the byte of file CSV -- //
List<List<dynamic>> convertByteIntoCSV(Uint8List bytes) {
return const CsvToListConverter().convert(utf8.decode(bytes));
}
String _getCategoryById(int id) {
switch (id) {
case 0:
return "generic";
case 2:
return "cycling";
case 11:
return "walking";
default:
return "generic";
}
}
// ------------- Get The path of application --- //
Future<String> get localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
/*
// ----- Read csv File ------- //
Future<List<dynamic>> readCSVFile(String path) async {
if (File(path).exists() == false) return List.empty();
final input = File(path).openRead();
final fields = await input
.transform(utf8.decoder)
.transform(const CsvToListConverter())
.toList();
return fields;
}
// ----- Read a file FIT --- //
Future<List<dynamic>> readFitFile(String path) async {
if (File(path).existsSync() == false) return List.empty();
final file = File(path);
final bytes = await file.readAsBytes();
final fitFile = FitFile.fromBytes(bytes);
return fitFile.toRows();
}
Future<List<dynamic>> readFitFileWhithFile(File file) async {
final bytes = await file.readAsBytes();
final fitFile = FitFile.fromBytes(bytes);
return fitFile.toRows();
}
List<dynamic> readFitFileWeb(Uint8List bytes) {
final fitFile = FitFile.fromBytes(bytes);
return fitFile.toRows();
}*/
/*
// --- A modifier si utilisé --- //
Future<bool> saveFileLocal(String nameFileWithExtension, String path) async {
/*
final outFile = File("${await localPath}\\Files\\$nameFileWithExtension");
if (outFile.existsSync() == false) {
outFile.createSync(recursive: true);
}
await outFile.writeAsString(await file.readAsString());
return true;*/
}*/
/*
// -- Check si le fichier existe localement -- //
Future<bool> fileExist(String filname) async {
Directory directory = Directory("${await localPath}\\Files\\");
if (!directory.existsSync()) {
print("Le dossier n'existe pas !");
return false;
}
List<FileSystemEntity> files = directory.listSync();
for (FileSystemEntity file in files) {
if (file.path.split("\\").last == filname) {
return true;
}
}
return false;
}*/
// --- Ligne utile --- //
//final csv = const ListToCsvConverter().convert(fitFile.toRows());
//await outFile.writeAsString(csv);*/
} }

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/manager_selected_activity.dart'; import 'package:smartfit_app_mobile/modele/manager_selected_activity.dart';
@ -24,4 +25,30 @@ class User extends ChangeNotifier {
listActivity.insert(index, activity); listActivity.insert(index, activity);
notifyListeners(); notifyListeners();
} }
// ------------ Fonction Calcul -------- //
double getTotalTimeAllActivity() {
double totalTime = 0.0;
for (ActivityOfUser activity in listActivity) {
totalTime += activity.time;
}
return totalTime;
}
double getTotalDenivelePositif() {
double totalDevPos = 0.0;
for (ActivityOfUser activity in listActivity) {
totalDevPos += activity.denivelePos;
}
return totalDevPos;
}
double getTotalDeniveleNegatif() {
double totalDevNeg = 0.0;
for (ActivityOfUser activity in listActivity) {
totalDevNeg += activity.denivelePos;
}
return totalDevNeg;
}
} }

@ -5,9 +5,9 @@ import 'package:csv/csv.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/modele/activity.dart'; import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart'; import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart'; import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:smartfit_app_mobile/modele/data_file.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -51,8 +51,8 @@ class ListActivityUtile {
notZero = true; notZero = true;
} }
Provider.of<User>(context, listen: false).addActivity(ActivityOfUser( Provider.of<User>(context, listen: false).addActivity(ActivityOfUser(
element["creation_date"].toString(),
element["category"].toString(), element["category"].toString(),
element["creation_date"].toString(),
element["uuid"].toString(), element["uuid"].toString(),
element["filename"].toString(), element["filename"].toString(),
/* /*
@ -73,15 +73,18 @@ class ListActivityUtile {
Future<Tuple2<bool, String>> _addFile( Future<Tuple2<bool, String>> _addFile(
Uint8List bytes, String filename, String token) async { Uint8List bytes, String filename, String token) async {
// -- Transormer le fit en CSV // -- Transormer le fit en CSV
DataFile dataFile = _managerFile.convertBytesFitFileIntoCSVList(bytes); Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData =
_managerFile.convertBytesFitFileIntoCSVListAndGetInfo(bytes);
String csvString = const ListToCsvConverter().convert(dataFile.csvData); String csvString = const ListToCsvConverter().convert(resultData.item2);
Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString)); Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString));
// --- Save Local // --- Save Local
// --- Api // --- Api
print("Start");
print(resultData.item3.toJson());
Tuple2<bool, String> result = await _strategy.uploadFileByte( Tuple2<bool, String> result = await _strategy.uploadFileByte(
token, byteCSV, filename, dataFile.category, dataFile.startTime); token, byteCSV, filename, resultData.item4, resultData.item3.startTime);
if (result.item1 == false) { if (result.item1 == false) {
return Tuple2(false, result.item2); return Tuple2(false, result.item2);
} }

Loading…
Cancel
Save