diff --git a/README.md b/README.md index 5cb1409..0b07dc3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # SmartFit Web and Mobile! -TODO: Description +TODO: Description + badge ## Getting Started diff --git a/lib/common_widget/container/list/list_activity_widget.dart b/lib/common_widget/container/list/list_activity_widget.dart index e815b60..807b468 100644 --- a/lib/common_widget/container/list/list_activity_widget.dart +++ b/lib/common_widget/container/list/list_activity_widget.dart @@ -1,6 +1,6 @@ +import 'package:smartfit_app_mobile/main.dart'; import 'package:smartfit_app_mobile/modele/activity_saver.dart'; import 'package:smartfit_app_mobile/modele/helper.dart'; -import 'package:smartfit_app_mobile/main.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; @@ -61,7 +61,7 @@ class _ListActivityWidget extends State { .managerSelectedActivity .removeSelectedActivity(activityObj.fileUuid); } - if (!Helper.isPlatformWeb()) { + if (!Helper.isPlatformWeb() && localDB.getSaveLocally()) { ActivitySaver actSaver = await ActivitySaver.create(); actSaver.deleteActivity(activityObj.fileUuid); localDB.removeActivity(activityObj.fileUuid); diff --git a/lib/modele/api/request_api.dart b/lib/modele/api/request_api.dart index 6a1cb15..2d983d1 100644 --- a/lib/modele/api/request_api.dart +++ b/lib/modele/api/request_api.dart @@ -267,7 +267,8 @@ class RequestApi implements IDataStrategy { final response = await http.get(Uri.parse('$urlApi/user/info'), headers: {'Authorization': token}); if (response.statusCode == 200) { - Map json = jsonDecode(response.body); + Map json = jsonDecode(response.body); + return Tuple2(true, json); } if (response.statusCode == 400) { @@ -285,7 +286,8 @@ class RequestApi implements IDataStrategy { @override Future getModeleAI(String token, String category) async { try { - final response = await http.post(Uri.parse('$urlApi/user/IA/$category')); + final response = await http.get(Uri.parse('$urlApi/user/ai/$category'), + headers: {'Authorization': token}); if (response.statusCode == 200) { Map json = jsonDecode(response.body); diff --git a/lib/modele/convertisseur.dart b/lib/modele/convertisseur.dart index 89e3ebc..41ab95d 100644 --- a/lib/modele/convertisseur.dart +++ b/lib/modele/convertisseur.dart @@ -2,7 +2,11 @@ class Convertisseur { // Mettre que des trucs static static double secondeIntoMinute(double seconde) { - return seconde / 60; + return (seconde / 60); + } + + static double milisecondeIntoMinute(double miliseconde) { + return (miliseconde / 60000); } static double msIntoKmh(double metreSeconde) { diff --git a/lib/modele/user.dart b/lib/modele/user.dart index 0cb1e5a..f230fcf 100644 --- a/lib/modele/user.dart +++ b/lib/modele/user.dart @@ -100,25 +100,20 @@ class User extends ChangeNotifier { Tuple2 result = await wrapper.getModeleAI(token, category, infoManager); if (!result.item1) return Tuple2(false, ActivityInfo()); - - // Appel pour avoir le model - //String jsonString = - // '{"coef": [270.63861280635473, 74.69699263779908, 1.9946527172333637, 0.03215810401413792, 0.3256805192289063], "intercept": [-335635.9890148213, -91874.0527070619, -2065.450392327813, -38.79838022998388, -291.590235396687]}'; - Map jsonMap = json.decode(result.item2); + String model = result.item2["model"]; + Map jsonMap = json.decode(model); // Transformer la date int dateMilli = date.millisecondsSinceEpoch; ActivityInfo activityInfo = ActivityInfo(); - activityInfo.distance = - jsonMap["coef"][0] * dateMilli + jsonMap["intercept"][0]; + activityInfo.bpmAvg = + (jsonMap["coef"][0] * dateMilli + jsonMap["intercept"][0]).toInt(); activityInfo.timeOfActivity = jsonMap["coef"][1] * dateMilli + jsonMap["intercept"][1]; - activityInfo.denivelePositif = - jsonMap["coef"][2] * dateMilli + jsonMap["intercept"][2]; activityInfo.vitesseAvg = + jsonMap["coef"][2] * dateMilli + jsonMap["intercept"][2]; + activityInfo.distance = jsonMap["coef"][3] * dateMilli + jsonMap["intercept"][3]; - activityInfo.bpmAvg = - jsonMap["coef"][4] * dateMilli + jsonMap["intercept"][4]; return Tuple2(true, activityInfo); } diff --git a/lib/modele/utile/home_view/home_view_util.dart b/lib/modele/utile/home_view/home_view_util.dart index 4cc56ad..63b236c 100644 --- a/lib/modele/utile/home_view/home_view_util.dart +++ b/lib/modele/utile/home_view/home_view_util.dart @@ -20,9 +20,11 @@ class HomeViewUtil { .getXWithTime(managerFile.fieldAltitude); List bpmSecondes2 = List.from(bpmSecondes); - - return DataHomeView(normaliserPremierElement(bpmSecondes), normaliserPremierElement(normaliserDeuxiemeElement(bpmSecondes2)), - normaliserPremierElement(normaliserDeuxiemeElement(vitesseSecondes)), normaliserPremierElement(altitudeSeconde)); + return DataHomeView( + normaliserPremierElement(bpmSecondes), + normaliserPremierElement(normaliserDeuxiemeElement(bpmSecondes2)), + normaliserPremierElement(normaliserDeuxiemeElement(vitesseSecondes)), + normaliserPremierElement(altitudeSeconde)); } List normaliserDeuxiemeElement(List liste) { @@ -41,21 +43,21 @@ class HomeViewUtil { } return liste; } + List normaliserPremierElement(List liste) { - // Trouver le plus grand élément dans le premier élément de chaque FlSpot - double maxElement = 0.0; - for (var spot in liste) { - if (spot.x > maxElement) { - maxElement = spot.x; + // Trouver le plus grand élément dans le premier élément de chaque FlSpot + double maxElement = 0.0; + for (var spot in liste) { + if (spot.x > maxElement) { + maxElement = spot.x; + } } + // Calculer le facteur de normalisation + double normalisationFactor = maxElement != 0.0 ? 100 / maxElement : 1.0; + // Mettre à jour tous les premiers éléments de la liste + for (int i = 0; i < liste.length; i++) { + liste[i] = FlSpot(liste[i].x * normalisationFactor, liste[i].y); + } + return liste; } - // Calculer le facteur de normalisation - double normalisationFactor = maxElement != 0.0 ? 100 / maxElement : 1.0; - // Mettre à jour tous les premiers éléments de la liste - for (int i = 0; i < liste.length; i++) { - liste[i] = FlSpot(liste[i].x * normalisationFactor, liste[i].y); - } - return liste; -} - } diff --git a/lib/modele/utile/list_activity/list_activity_utile.dart b/lib/modele/utile/list_activity/list_activity_utile.dart index dd79aa0..7c525aa 100644 --- a/lib/modele/utile/list_activity/list_activity_utile.dart +++ b/lib/modele/utile/list_activity/list_activity_utile.dart @@ -5,7 +5,6 @@ import 'package:smartfit_app_mobile/modele/activity_saver.dart'; import 'package:smartfit_app_mobile/modele/helper.dart'; import 'dart:convert'; import 'dart:io'; -import 'dart:typed_data'; import 'package:csv/csv.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -91,6 +90,9 @@ class ListActivityUtile { String csvString = const ListToCsvConverter().convert(resultData.item2); Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString)); + File x = await File("${await _managerFile.localPath}\\what") + .writeAsString(csvString); + Tuple2 result = await api.uploadFileByte( token, byteCSV, diff --git a/lib/view/home/mobile/mobile_homeview.dart b/lib/view/home/mobile/mobile_homeview.dart index a209df8..0a43a10 100644 --- a/lib/view/home/mobile/mobile_homeview.dart +++ b/lib/view/home/mobile/mobile_homeview.dart @@ -29,6 +29,7 @@ class _MobileHomeView extends State { context.watch().managerSelectedActivity; data = HomeViewUtil().initData(context); + // -- BPM -- // data.maxBPM = managerSelectedActivity.activitySelected.first.activityInfo.bpmMax; @@ -36,7 +37,6 @@ class _MobileHomeView extends State { managerSelectedActivity.activitySelected.first.activityInfo.bpmMin; int avgBpm = managerSelectedActivity.activitySelected.first.activityInfo.bpmAvg; - // -- Altitude -- // double minAltitude = managerSelectedActivity.activitySelected.first.activityInfo.altitudeMin; @@ -48,12 +48,12 @@ class _MobileHomeView extends State { double maxSpeed = managerSelectedActivity.getMaxSpeedAllActivitySelected(); double avgSpeed = managerSelectedActivity.getAvgSpeedAllActivitySelected(); double minSpeed = managerSelectedActivity.getMinSpeedAllActivitySelected(); - data.maxSpeed = maxSpeed; data.time = context .watch() .managerSelectedActivity .getTimeAllActivitySelected(); + return Scaffold( backgroundColor: TColor.white, body: SingleChildScrollView( diff --git a/lib/view/home/prediction_view.dart b/lib/view/home/prediction_view.dart index 400681e..4a4da7f 100644 --- a/lib/view/home/prediction_view.dart +++ b/lib/view/home/prediction_view.dart @@ -5,6 +5,7 @@ import 'package:smartfit_app_mobile/common/colo_extension.dart'; import 'package:smartfit_app_mobile/common_widget/button/round_button.dart'; import 'package:smartfit_app_mobile/common_widget/container/workout_row/workout_row.dart'; import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart'; +import 'package:smartfit_app_mobile/modele/convertisseur.dart'; import 'package:smartfit_app_mobile/modele/manager_file.dart'; import 'package:smartfit_app_mobile/modele/user.dart'; import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; @@ -45,14 +46,15 @@ class _PredictionState extends State { @override Widget build(BuildContext context) { - var media = MediaQuery.of(context).size; List listCategory = [_managerFile.marche, _managerFile.velo]; void prediction() async { InfoMessage tmp = InfoMessage(); - setState(() { - lastWorkoutArr[0]["value"] = "null"; - }); + + /* + if (selectedCategory != _managerFile.marche || + selectedCategory != _managerFile.velo) return;*/ + Tuple2 resultat = await Provider.of(context, listen: false) .predictActivity(DateTime.now(), selectedCategory, tmp); @@ -154,7 +156,6 @@ class _PredictionState extends State { title: "Valider", onPressed: () async { prediction(); - setState(() {}); }), const SizedBox(height: 20), ListView.builder( @@ -163,7 +164,7 @@ class _PredictionState extends State { shrinkWrap: true, itemCount: lastWorkoutArr.length, itemBuilder: (context, index) { - var wObj = lastWorkoutArr[index] as Map ?? {}; + var wObj = lastWorkoutArr[index]; return InkWell( child: WorkoutRow(wObj: wObj), ); diff --git a/lib/view/profile/all_platforme/profile_view_allplatforme.dart b/lib/view/profile/all_platforme/profile_view_allplatforme.dart index 4406961..98dcfd6 100644 --- a/lib/view/profile/all_platforme/profile_view_allplatforme.dart +++ b/lib/view/profile/all_platforme/profile_view_allplatforme.dart @@ -7,7 +7,11 @@ import 'package:smartfit_app_mobile/common_widget/container/profile/profile_comp import 'package:smartfit_app_mobile/common_widget/container/profile/profile_entete.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_info_user.dart'; import 'package:smartfit_app_mobile/common_widget/container/profile/profile_other.dart'; +import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart'; import 'package:smartfit_app_mobile/modele/user.dart'; +import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; +import 'package:smartfit_app_mobile/view/login/signup_view.dart'; +import 'package:tuple/tuple.dart'; class ProfileViewAllPlatforme extends StatefulWidget { final bool offlineSave; @@ -26,7 +30,32 @@ class _ProfileViewAllPlatforme extends State { @override Widget build(BuildContext context) { + ApiWrapper wrapper = ApiWrapper(); String username = context.watch().username; + InfoMessage infoManager = InfoMessage(); + + void logOff() { + // Appel ici pour logOff + /* + if (!result.item1) { + // Affiché erreur + } else { + Navigator.push(context, + MaterialPageRoute(builder: (context) => const LoginView())); + }*/ + } + + void deleteUser() async { + // Ne marche pas !! + Tuple2 result = await wrapper.deleteUser( + Provider.of(context, listen: false).token, infoManager); + if (!result.item1) { + // Affiché erreur + } else { + Navigator.push(context, + MaterialPageRoute(builder: (context) => const SignUpView())); + } + } return Scaffold( appBar: AppBar( @@ -59,8 +88,6 @@ class _ProfileViewAllPlatforme extends State { const SizedBox( height: 25, ), - // TODO: Download/Delete (local) all users files on toggle ? - // TODO: Display size of download in Mo Visibility( visible: isNative, child: const Column( @@ -72,7 +99,39 @@ class _ProfileViewAllPlatforme extends State { ) ], )), - ProfileOther(widget.otherArr) + ProfileOther(widget.otherArr), + const SizedBox( + height: 25, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + style: TextButton.styleFrom( + backgroundColor: TColor.primaryColor1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8))), + onPressed: logOff, + child: const Text('Déconnexion', + style: TextStyle(color: Colors.black)), + ), + const SizedBox( + width: 25, + ), + TextButton( + style: TextButton.styleFrom( + backgroundColor: TColor.primaryColor1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8))), + onPressed: deleteUser, + child: const Text('Supprimer son compte', + style: TextStyle(color: Colors.black)), + ), + ], + ), + const SizedBox( + height: 25, + ) ], ), ), diff --git a/test/widget_test.dart b/test/widget_test.dart index 462baf5..92d419e 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -5,17 +5,25 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:smartfit_app_mobile/main.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/api_wrapper.dart'; +import 'package:smartfit_app_mobile/modele/api/request_api.dart'; +import 'package:smartfit_app_mobile/modele/user.dart'; +import 'package:smartfit_app_mobile/modele/utile/signup_user.dart'; +import 'package:tuple/tuple.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { + testWidgets('Test login', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + //await tester.pumpWidget(const MyApp()); - // Verify that our counter starts at 0. + //expect(find.text('Se connecter'), findsOneWidget); + + /* expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); @@ -25,6 +33,40 @@ void main() { // Verify that our counter has incremented. expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + expect(find.text('1'), findsOneWidget);*/ + }); + + // Ce n'est pas possible de faire des test http => + //To test code that needs an HttpClient, provide your own HttpClient + //implementation to the code under test, so that your test can + //consistently provide a testable response to the code under test. + /* + test("Unit Test -- Create and delete User", () async { + final SignUp utilSignUp = SignUp(); + final RequestApi requestApi = RequestApi(); + + Tuple2 result = + await utilSignUp.createUser("test@gmail.com", "test", "test"); + + expect(result.item1, true); + + Tuple2 delete = await requestApi.deleteUser(result.item2); + expect(delete.item1, true); + });*/ + + test("User", () { + User user = User(); + ActivityOfUser activityOfUser = + ActivityOfUser(ActivityInfo(), "CATEGORIE", "0000", "NAMEFILE"); + + expect(user.listActivity.length, 0); + + user.addActivity(activityOfUser); + + expect(user.listActivity.length, 1); + + user.removeActivity(activityOfUser); + + expect(user.listActivity.length, 0); }); }