diff --git a/lib/modele/api/api_wrapper.dart b/lib/modele/api/api_wrapper.dart index 48ee173..ecd932a 100644 --- a/lib/modele/api/api_wrapper.dart +++ b/lib/modele/api/api_wrapper.dart @@ -193,6 +193,16 @@ class ApiWrapper { return res; } + + Future getModeleAI( + String token, String category, InfoMessage infoManager) async { + await init(); + if (handleOffline(infoManager)) return const Tuple2(false, "offline"); + + Tuple2 res = await api.getModeleAI(token, category); + if (!res.item1) infoManager.displayMessage(noConnectionMessage, true); + return res; + } } extension StringExtension on String { diff --git a/lib/modele/api/i_data_strategy.dart b/lib/modele/api/i_data_strategy.dart index 54ea65d..b80feb2 100644 --- a/lib/modele/api/i_data_strategy.dart +++ b/lib/modele/api/i_data_strategy.dart @@ -42,4 +42,7 @@ abstract class IDataStrategy { // Update email, password, username Future> modifAttribut( String token, String nameAttribut, String newValue); + + // + Future getModeleAI(String token, String category); } diff --git a/lib/modele/api/request_api.dart b/lib/modele/api/request_api.dart index bf525af..6a1cb15 100644 --- a/lib/modele/api/request_api.dart +++ b/lib/modele/api/request_api.dart @@ -281,4 +281,20 @@ class RequestApi implements IDataStrategy { } return const Tuple2(false, "Fail"); } + + @override + Future getModeleAI(String token, String category) async { + try { + final response = await http.post(Uri.parse('$urlApi/user/IA/$category')); + + if (response.statusCode == 200) { + Map json = jsonDecode(response.body); + return Tuple2(true, json); + } else { + return const Tuple2(false, "Fail"); + } + } on SocketException catch (_) { + return const Tuple2(false, "No connection"); + } + } } diff --git a/lib/modele/local_db/request_local.dart b/lib/modele/local_db/request_local.dart index a8fcb26..19aa25f 100644 --- a/lib/modele/local_db/request_local.dart +++ b/lib/modele/local_db/request_local.dart @@ -86,4 +86,9 @@ class RequestLocal implements IDataStrategy { Future deleteFile(String token, String fileUuid) async { throw Exception("Not Implemented"); } + + @override + Future getModeleAI(String token, String category) async { + return const Tuple2(false, "Not implemented"); + } } diff --git a/lib/modele/manager_file.dart b/lib/modele/manager_file.dart index 90482a6..0d26cae 100644 --- a/lib/modele/manager_file.dart +++ b/lib/modele/manager_file.dart @@ -43,6 +43,7 @@ class ManagerFile { // -- Getter categorie String get marche => _marche; + String get velo => _velo; String get generic => _generic; List allowedFieldWalking = List.empty(growable: true); diff --git a/lib/modele/user.dart b/lib/modele/user.dart index 3a6f428..0cb1e5a 100644 --- a/lib/modele/user.dart +++ b/lib/modele/user.dart @@ -3,7 +3,10 @@ import 'dart:convert'; import 'package:flutter/material.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/manager_selected_activity.dart'; +import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; +import 'package:tuple/tuple.dart'; class User extends ChangeNotifier { String username = "VOID"; @@ -91,11 +94,17 @@ class User extends ChangeNotifier { return map; } - ActivityInfo predictActivity(DateTime date) { + Future> predictActivity( + DateTime date, String category, InfoMessage infoManager) async { + ApiWrapper wrapper = ApiWrapper(); + 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(jsonString); + //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); // Transformer la date int dateMilli = date.millisecondsSinceEpoch; @@ -111,6 +120,6 @@ class User extends ChangeNotifier { activityInfo.bpmAvg = jsonMap["coef"][4] * dateMilli + jsonMap["intercept"][4]; - return activityInfo; + return Tuple2(true, activityInfo); } } diff --git a/lib/view/home/prediction_view.dart b/lib/view/home/prediction_view.dart index 71c0641..f521ca3 100644 --- a/lib/view/home/prediction_view.dart +++ b/lib/view/home/prediction_view.dart @@ -1,8 +1,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:provider/provider.dart'; 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/manager_file.dart'; +import 'package:smartfit_app_mobile/modele/user.dart'; +import 'package:smartfit_app_mobile/modele/utile/info_message.dart'; +import 'package:tuple/tuple.dart'; class Prediction extends StatefulWidget { const Prediction({Key? key}) : super(key: key); @@ -16,36 +22,59 @@ class _PredictionState extends State { { "name": "Temps", "image": "assets/img/time-icon2.svg", - "value": "200 s", + "value": "..", }, { "name": "Rythme cardiaque", "image": "assets/img/bpm2-icon.svg", - "value": "120 BPM", + "value": "..", }, { "name": "Vitesse", "image": "assets/img/vitesse2-icon.svg", - "value": "3 m/s", + "value": "..", }, { "name": "Distance", "image": "assets/img/distance2-icon.svg", - "value": "300 m", + "value": "..", } ]; + final ManagerFile _managerFile = ManagerFile(); + String selectedCategory = "Choisir type d'activité"; @override Widget build(BuildContext context) { var media = MediaQuery.of(context).size; + List listCategory = [_managerFile.marche, _managerFile.velo]; + + void prediction() async { + InfoMessage tmp = InfoMessage(); + setState(() { + print("lol"); + lastWorkoutArr[0]["Value"] = "null"; + }); + Tuple2 resultat = + await Provider.of(context, listen: false) + .predictActivity(DateTime.now(), selectedCategory, tmp); + if (!resultat.item1) return; + setState(() { + lastWorkoutArr[0]["Value"] = + resultat.item2.timeOfActivity.toStringAsFixed(2); + lastWorkoutArr[1]["Value"] = resultat.item2.bpmAvg.toStringAsFixed(2); + lastWorkoutArr[2]["Value"] = + resultat.item2.vitesseAvg.toStringAsFixed(2); + lastWorkoutArr[3]["Value"] = resultat.item2.distance.toStringAsFixed(2); + }); + } return Scaffold( body: Padding( - padding: EdgeInsets.symmetric(horizontal: 20.0), + padding: const EdgeInsets.symmetric(horizontal: 20.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox(height: 40), + const SizedBox(height: 40), Text( "Prédiction", style: TextStyle( @@ -54,21 +83,20 @@ class _PredictionState extends State { fontWeight: FontWeight.w700, ), ), - SizedBox(height: 20), - Row( - children: [ - - ], + const SizedBox(height: 20), + const Row( + children: [], ), Container( decoration: BoxDecoration( color: TColor.lightGray, boxShadow: [ BoxShadow( - color: Color.fromARGB(255, 234, 234, 234).withOpacity(0.9), + color: const Color.fromARGB(255, 234, 234, 234) + .withOpacity(0.9), spreadRadius: 2, blurRadius: 5, - offset: Offset(0, 2), + offset: const Offset(0, 2), ), ], borderRadius: BorderRadius.circular(15), @@ -90,7 +118,7 @@ class _PredictionState extends State { Expanded( child: DropdownButtonHideUnderline( child: DropdownButton( - items: ["Walking", "Cycling"] + items: listCategory .map((name) => DropdownMenuItem( value: name, child: Text( @@ -102,10 +130,14 @@ class _PredictionState extends State { ), )) .toList(), - onChanged: (value) {}, + onChanged: (value) { + setState(() { + selectedCategory = value!; + }); + }, isExpanded: true, hint: Text( - "Choisir type d'activité", + selectedCategory, style: TextStyle( color: TColor.gray, fontSize: 12, @@ -115,25 +147,23 @@ class _PredictionState extends State { ), ), // Bouton "Valider" prenant 30% de la largeur du parent - ], ), ), - SizedBox(height: 20), - RoundButton( + const SizedBox(height: 20), + RoundButton( title: "Valider", onPressed: () async { - setState(() {}); + prediction(); }), - SizedBox(height: 20), + const SizedBox(height: 20), ListView.builder( padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: lastWorkoutArr.length, itemBuilder: (context, index) { - var wObj = - lastWorkoutArr[index] as Map ?? {}; + var wObj = lastWorkoutArr[index] as Map ?? {}; return InkWell( child: WorkoutRow(wObj: wObj), );