je vais me tirer une balle dans lcrane

pull/4/head
remrem 1 year ago
commit 425bc391a2

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><style>.cls-1{fill:#231f20;}</style></defs><g id="maps"><path class="cls-1" d="M29,6.94,20.48,4.11h-.06A1,1,0,0,0,20,4a.89.89,0,0,0-.43.11h-.08L16.64,5.19a5,5,0,0,0-1-1.59,5,5,0,0,0-7.9.77,4.87,4.87,0,0,0-.47,1L3.94,4.26A1.47,1.47,0,0,0,2,5.66V7A1,1,0,0,0,4,7V6.39l3,1a5,5,0,0,0,.51,1.87l3.57,7.19a1,1,0,0,0,1.8,0l3.57-7.19A5.06,5.06,0,0,0,17,7.41a1.47,1.47,0,0,0,0-.21l2-.76V25.31l-6,2.25V20a1,1,0,0,0-2,0v7.61L4,25.28V11a1,1,0,0,0-2,0V25.66a1.48,1.48,0,0,0,1,1.4l8.51,2.83h.07A.92.92,0,0,0,12,30a1,1,0,0,0,.44-.11h.07L20,27.06l2.66.89a1,1,0,0,0,.64-1.9L21,25.28V6.39l7,2.33V27.61l-.68-.23a1,1,0,0,0-.64,1.9l1.38.46a1.48,1.48,0,0,0,.46.08,1.53,1.53,0,0,0,.87-.28,1.5,1.5,0,0,0,.61-1.2v-20A1.48,1.48,0,0,0,29,6.94ZM14.68,8.37,12,13.75,9.32,8.37a3,3,0,0,1,.14-2.95A3,3,0,0,1,14.19,5a3.07,3.07,0,0,1,.8,2.3A3.18,3.18,0,0,1,14.68,8.37Z"/><path class="cls-1" d="M12,6h0a1,1,0,1,0,1,1A1,1,0,0,0,12,6Z"/></g></svg>

After

Width:  |  Height:  |  Size: 974 B

@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
class TColor {
static Color get primaryColor1 => Color(0xffF09932);
static Color get primaryColor2 => Color(0xffFFDCB2);
static Color get primaryColor1 => const Color(0xffF09932);
static Color get primaryColor2 => const Color(0xffFFDCB2);
static Color get secondaryColor1 => Color(0xff6131AD);
static Color get secondaryColor2 => Color(0xffD4B9FF);
static Color get secondaryColor1 => const Color(0xff6131AD);
static Color get secondaryColor2 => const Color(0xffD4B9FF);
static List<Color> get primaryG => [primaryColor2, primaryColor1];
static List<Color> get secondaryG => [secondaryColor2, secondaryColor1];

@ -11,11 +11,11 @@ class ContainerStats extends StatelessWidget {
final String designation;
final IconData icon;
@override
@override
Widget build(BuildContext context) {
return ScreenTypeLayout.builder(
mobile: (_) => MobileContainerStats(this.value, this.designation, this.icon),
desktop: (_) => WebContainerStats(this.value, this.designation, this.icon),
mobile: (_) => MobileContainerStats(value, designation, icon),
desktop: (_) => WebContainerStats(value, designation, icon),
);
}
}

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/common_widget/container/mobile/mobile_container_stats_activities.dart';
import 'package:smartfit_app_mobile/common_widget/container/web/web_container_stats_activities.dart';
class ContainerStatsActivities extends StatelessWidget {
const ContainerStatsActivities(
this.value,
this.designation,
this.icon, {
Key? key,
}) : super(key: key);
final String value;
final String designation;
final IconData icon;
@override
Widget build(BuildContext context) {
return ScreenTypeLayout.builder(
mobile: (_) => MobileContainerStatsActivities(value, designation, icon),
desktop: (_) => WebContainerStatsActivities(value, designation, icon),
);
}
}

@ -2,22 +2,25 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common_widget/container/workout_row.dart';
import 'package:smartfit_app_mobile/modele/api/api_wrapper.dart';
import 'package:smartfit_app_mobile/modele/activity.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:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
import 'package:tuple/tuple.dart';
class ListActivity extends StatefulWidget {
const ListActivity({Key? key}) : super(key: key);
class ListActivityWidget extends StatefulWidget {
const ListActivityWidget({Key? key}) : super(key: key);
@override
State<ListActivity> createState() => _ListActivity();
State<ListActivityWidget> createState() => _ListActivityWidget();
}
class _ListActivity extends State<ListActivity> {
class _ListActivityWidget extends State<ListActivityWidget> {
final ApiWrapper api = ApiWrapper();
final InfoMessage infoManager = InfoMessage();
final ListActivityUtile _utile = ListActivityUtile();
final ManagerFile managerFile = ManagerFile();
@override
Widget build(BuildContext context) {
@ -29,9 +32,16 @@ class _ListActivity extends State<ListActivity> {
shrinkWrap: true,
itemCount: Provider.of<User>(context, listen: true).listActivity.length,
itemBuilder: (context, index) {
var activityObj =
ActivityOfUser activityObj =
Provider.of<User>(context, listen: true).listActivity[index];
var activityMap = activityObj.toMap();
Map<String, dynamic> activityMap;
// -- Si categorie == marche
if (activityObj.category == managerFile.marche) {
activityMap = activityObj.toMapWalking();
} else {
// -- Default -- //
activityMap = activityObj.toMapGeneric();
}
return InkWell(
onTap: () {},
@ -60,6 +70,7 @@ class _ListActivity extends State<ListActivity> {
Provider.of<User>(context, listen: false)
.managerSelectedActivity
.removeSelectedActivity(activityObj.fileUuid);
setState(() {});
return;
}

@ -36,6 +36,7 @@ class MobileContainerStats extends StatelessWidget {
icon: icon,
iconColor: TColor.white,
iconBackground: TColor.secondaryColor1,
sizeIcon: 12,
),
Align(
alignment: Alignment.bottomLeft,

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/stats.dart';
class MobileContainerStatsActivities extends StatelessWidget {
const MobileContainerStatsActivities(
this.value,
this.designation,
this.icon, {
Key? key,
}) : super(key: key);
final String value;
final String designation;
final IconData icon;
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Container(
height: media.width * 0.4,
width: media.width * 0.27,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: const Color(0xffe1e1e1),
),
boxShadow: const [
BoxShadow(
color: Colors.black12,
offset: Offset(3, 3),
blurRadius: 3,
),
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center, // Centrer horizontalement
mainAxisAlignment: MainAxisAlignment.center,
children: [
StatIcon(
icon: icon,
iconColor: TColor.white,
iconBackground: TColor.secondaryColor1,
sizeIcon: 30.0,
),
const SizedBox(height: 20), // Espacement entre l'icône et le texte
Text(
designation,
style: const TextStyle(fontSize: 12),
textAlign: TextAlign.center,
),
Text(
value,
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.w800,
),
textAlign: TextAlign.center,
),
],
),
);
}
}

@ -3,9 +3,16 @@ import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/container/container_stats.dart';
class MobileLigneContainerStats extends StatelessWidget {
const MobileLigneContainerStats(this.value1, this.value2, this.value3,
this.designation1, this.designation2, this.designation3,
this.icon1, this.icon2, this.icon3,
const MobileLigneContainerStats(
this.value1,
this.value2,
this.value3,
this.designation1,
this.designation2,
this.designation3,
this.icon1,
this.icon2,
this.icon3,
{Key? key})
: super(key: key);
@ -21,13 +28,11 @@ class MobileLigneContainerStats extends StatelessWidget {
final IconData icon2;
final IconData icon3;
@override
Widget build(BuildContext context) {
return Column(
children: [
Divider(height: 30),
const Divider(height: 30),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Row(
@ -39,7 +44,7 @@ class MobileLigneContainerStats extends StatelessWidget {
fontWeight: FontWeight.w800,
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
Icon(
Icons.pie_chart_rounded,
size: 15,
@ -48,24 +53,21 @@ class MobileLigneContainerStats extends StatelessWidget {
],
),
),
SizedBox(height: 20),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStats(value1, designation1, icon1),
const SizedBox(width: 20),
ContainerStats(value2, designation2, icon2),
const SizedBox(width: 20),
ContainerStats(value3, designation3, icon3),
],)
),
Divider(height: 30),
const SizedBox(height: 20),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStats(value1, designation1, icon1),
const SizedBox(width: 20),
ContainerStats(value2, designation2, icon2),
const SizedBox(width: 20),
ContainerStats(value3, designation3, icon3),
],
)),
const Divider(height: 30),
],
);
}
}

@ -1,35 +1,48 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common_widget/title_subtitle_cell.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
class ProfileInfoUser extends StatelessWidget {
const ProfileInfoUser({super.key});
@override
Widget build(BuildContext context) {
return const Row(
return Row(
children: [
Expanded(
child: TitleSubtitleCell(
title: "??? cm",
subtitle: "Taille",
title: context.watch<User>().listActivity.length.toString(),
subtitle: "Nombre d'activité",
),
),
SizedBox(
const SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? kg",
subtitle: "Poids",
title: context.watch<User>().getTotalTimeAllActivity().toString(),
subtitle: "Temps en activité",
),
),
SizedBox(
const SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title: "?? ans",
subtitle: "Age",
title:
"${context.watch<User>().getTotalDenivelePositif().toString()} + m",
subtitle: "Total dénivelé positif",
),
),
const SizedBox(
width: 15,
),
Expanded(
child: TitleSubtitleCell(
title:
"${context.watch<User>().getTotalDeniveleNegatif().toString()} - m",
subtitle: "Total dénivelé négatif",
),
),
],

@ -13,7 +13,7 @@ class WebContainerStats extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 70,
height: 80,
width: 70,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(vertical: 5),
@ -36,6 +36,7 @@ class WebContainerStats extends StatelessWidget {
icon: icon,
iconColor: TColor.white,
iconBackground: TColor.secondaryColor1,
sizeIcon: 8.0,
),
Align(
alignment: Alignment.bottomLeft,

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/stats.dart';
class WebContainerStatsActivities extends StatelessWidget {
const WebContainerStatsActivities(
this.value,
this.designation,
this.icon, {
Key? key,
}) : super(key: key);
final String value;
final String designation;
final IconData icon;
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
return Container(
height: media.width * 0.2,
width: media.width * 0.3,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: const Color(0xffe1e1e1),
),
boxShadow: const [
BoxShadow(
color: Colors.black12,
offset: Offset(3, 3),
blurRadius: 3,
),
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center, // Centrer horizontalement
mainAxisAlignment: MainAxisAlignment.center,
children: [
StatIcon(
icon: icon,
iconColor: TColor.white,
iconBackground: TColor.secondaryColor1,
sizeIcon: 40.0,
),
const SizedBox(height: 40), // Espacement entre l'icône et le texte
Text(
designation,
style: const TextStyle(fontSize: 15),
textAlign: TextAlign.center,
),
Text(
value,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w800,
),
textAlign: TextAlign.center,
),
],
),
);
}
}

@ -3,9 +3,16 @@ import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/container/container_stats.dart';
class WebLigneContainerStats extends StatelessWidget {
const WebLigneContainerStats(this.value1, this.value2, this.value3,
this.designation1, this.designation2, this.designation3,
this.icon1, this.icon2, this.icon3,
const WebLigneContainerStats(
this.value1,
this.value2,
this.value3,
this.designation1,
this.designation2,
this.designation3,
this.icon1,
this.icon2,
this.icon3,
{Key? key})
: super(key: key);
@ -21,11 +28,10 @@ class WebLigneContainerStats extends StatelessWidget {
final IconData icon2;
final IconData icon3;
@override
Widget build(BuildContext context) {
return Column(
children: [
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Column(
@ -37,7 +43,7 @@ class WebLigneContainerStats extends StatelessWidget {
fontWeight: FontWeight.w800,
),
),
SizedBox(width: 8),
const SizedBox(width: 8),
Icon(
Icons.pie_chart_rounded,
size: 15,
@ -46,24 +52,21 @@ class WebLigneContainerStats extends StatelessWidget {
],
),
),
SizedBox(height: 20),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStats(value1, designation1, icon1),
const SizedBox(width: 20),
ContainerStats(value2, designation2, icon2),
const SizedBox(width: 20),
ContainerStats(value3, designation3, icon3),
],)
),
Divider(height: 30),
const SizedBox(height: 20),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStats(value1, designation1, icon1),
const SizedBox(width: 20),
ContainerStats(value2, designation2, icon2),
const SizedBox(width: 20),
ContainerStats(value3, designation3, icon3),
],
)),
const Divider(height: 30),
],
);
}
}

@ -25,7 +25,7 @@ class WorkoutRow extends StatelessWidget {
decoration: BoxDecoration(
border: Border.all(
color: isSelected
? Color.fromARGB(255, 144, 252, 148)
? const Color.fromARGB(255, 144, 252, 148)
: Colors.transparent,
width: 2.0,
),
@ -33,12 +33,12 @@ class WorkoutRow extends StatelessWidget {
),
child: Material(
color: isSelected
? Color.fromARGB(255, 240, 255, 240)
? const Color.fromARGB(255, 240, 255, 240)
: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(10), // Utiliser le même borderRadius
splashColor: Color.fromARGB(255, 42, 94, 44)
splashColor: const Color.fromARGB(255, 42, 94, 44)
.withOpacity(0.3), // Couleur du fond au survol
onTap: onClick,
child: Padding(
@ -60,14 +60,28 @@ class WorkoutRow extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
wObj["categorie"].toString(),
"Type : ${wObj["categorie"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
wObj["date"].toString(),
"Date : ${wObj["date"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
"Temps : ${wObj["time"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,
),
),
Text(
"Dénivelé positif : ${wObj["DenivelePositif"].toString()}",
style: TextStyle(
color: TColor.black,
fontSize: 12,

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/common_widget/graph/mobile/mobile_bpm_by_time.dart';
import 'package:smartfit_app_mobile/common_widget/graph/web/web_bpm_by_time.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
@ -8,19 +9,20 @@ class BpmByTime extends StatefulWidget {
final Size media;
final DataHomeView data;
const BpmByTime(this.media, this.data, {Key? key})
: super(key: key);
const BpmByTime(this.media, this.data, {Key? key}) : super(key: key);
@override
State<BpmByTime> createState() => _BpmByTime();
}
class _BpmByTime extends State<BpmByTime> {
@override
@override
Widget build(BuildContext context) {
final FuncBpmByTime funcBpm = FuncBpmByTime(widget.data);
return ScreenTypeLayout.builder(
mobile: (_) => MobileBpmByTime(widget.media, widget.data),
desktop: (_) => WebBpmByTime(widget.media, widget.data),
mobile: (_) => MobileBpmByTime(widget.media, widget.data),
desktop: (_) => WebBpmByTime(widget.media, widget.data, funcBpm),
);
}
}
}

@ -17,6 +17,19 @@ class FuncBpmAndSpeedByTime {
reservedSize: 40,
);
SideTitles get leftTitles => SideTitles(
getTitlesWidget: leftTitleWidgets,
showTitles: true,
interval: 20,
reservedSize: 40,
);
SideTitles get bottomTitles => SideTitles(
getTitlesWidget: bottomTitleWidgets,
showTitles: true,
interval: 20,
reservedSize: 20,
);
late final lineBarsData = [
LineChartBarData(
spots: data.bpmSecondes,
@ -38,25 +51,95 @@ class FuncBpmAndSpeedByTime {
late final tooltipsOnBar = lineBarsData[0];
Widget rightTitleWidgets(double value, TitleMeta meta) {
double interval = data.maxBPM / 5;
String text;
switch (value.toInt()) {
case 0:
text = '0 BPM';
break;
case 20:
text = "${(interval).toStringAsFixed(2)} BPM";
break;
case 40:
text = "${(interval * 2).toStringAsFixed(2)} BPM";
break;
case 60:
text = "${(interval * 3).toStringAsFixed(2)} BPM";
break;
case 80:
text = "${(interval * 4).toStringAsFixed(2)} BPM";
break;
case 100:
text = "${interval * 5} BPM";
break;
default:
return Container();
}
return Text(text,
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}
Widget bottomTitleWidgets(double value, TitleMeta meta) {
double interval = data.time / 5;
String text;
switch (value) {
case 0:
text = '0 s';
break;
case 20:
text = "${(interval).toStringAsFixed(2)} s";
break;
case 40:
text = "${(interval * 2).toStringAsFixed(2)} s";
break;
case 60:
text = "${(interval * 3).toStringAsFixed(2)} s";
break;
case 80:
text = "${(interval * 4).toStringAsFixed(2)} s";
break;
case 100:
text = "${(interval * 5).toStringAsFixed(2)} s";
break;
default:
return Container();
}
return Text(text,
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}
Widget leftTitleWidgets(double value, TitleMeta meta) {
double interval = data.maxSpeed / 5;
String text;
switch (value.toInt()) {
case 0:
text = '0%';
text = '0 m/s';
break;
case 20:
text = '20%';
text = "${(interval / 5).toStringAsFixed(2)} m/s";
break;
case 40:
text = '40%';
text = "${(interval * 2).toStringAsFixed(2)} m/s";
break;
case 60:
text = '60%';
text = "${(interval * 3).toStringAsFixed(2)} m/s";
break;
case 80:
text = '80%';
text = "${(interval * 4).toStringAsFixed(2)} m/s";
break;
case 100:
text = '100%';
text = "${(interval * 5).toStringAsFixed(2)} m/s";
break;
default:
return Container();

@ -0,0 +1,95 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
class FuncBpmByTime {
final DataHomeView data;
FuncBpmByTime(this.data);
SideTitles get rightTitles => SideTitles(
getTitlesWidget: rightTitleWidgets,
showTitles: true,
interval: 20,
reservedSize: 40,
);
SideTitles get bottomTitles => SideTitles(
getTitlesWidget: bottomTitleWidgets,
showTitles: true,
interval: 20,
reservedSize: 20,
);
Widget rightTitleWidgets(double value, TitleMeta meta) {
int minBpm = data.minBPM;
int maxBpm = data.maxBPM;
double interval = (maxBpm - minBpm) / 5;
String text;
switch (value.toInt()) {
case 0:
text = "${(minBpm).toStringAsFixed(2)} BPM";
break;
case 20:
text = "${(minBpm + interval).toStringAsFixed(2)} BPM";
break;
case 40:
text = "${(minBpm + interval * 2).toStringAsFixed(2)} BPM";
break;
case 60:
text = "${(minBpm + interval * 3).toStringAsFixed(2)} BPM";
break;
case 80:
text = "${(minBpm + interval * 4).toStringAsFixed(2)} BPM";
break;
case 100:
text = "${(maxBpm).toStringAsFixed(2)} BPM";
break;
default:
return Container();
}
return Text(text,
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}
Widget bottomTitleWidgets(double value, TitleMeta meta) {
double interval = data.time / 5;
String text;
switch (value) {
case 0:
text = '0 s';
break;
case 20:
text = "${(interval).toStringAsFixed(2)} s";
break;
case 40:
text = "${(interval * 2).toStringAsFixed(2)} s";
break;
case 60:
text = "${(interval * 3).toStringAsFixed(2)} s";
break;
case 80:
text = "${(interval * 4).toStringAsFixed(2)} s";
break;
case 100:
text = "${(interval * 5).toStringAsFixed(2)} s";
break;
default:
return Container();
}
return Text(text,
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
}
}

@ -127,7 +127,7 @@ class GraphPainter extends CustomPainter {
..style = PaintingStyle.fill;
Paint dotOutlinePaint = Paint()
..color = ui.Color.fromARGB(255, 236, 236, 236).withAlpha(200)
..color = const ui.Color.fromARGB(255, 236, 236, 236).withAlpha(200)
..strokeWidth = 8;
Paint dotCenter = Paint()

@ -20,10 +20,22 @@ class MobileGraphAltitudeByTime extends StatefulWidget {
class _MobileGraphAltitudeByTime extends State<MobileGraphAltitudeByTime> {
@override
Widget build(BuildContext context) {
final double maxY =
context.watch<User>().managerSelectedActivity.getMaxAltitude() + 2;
final double minY =
context.watch<User>().managerSelectedActivity.getMinAltitude() - 2;
final double maxY = context
.watch<User>()
.managerSelectedActivity
.activitySelected
.first
.activityInfo
.altitudeMax +
2;
final double minY = context
.watch<User>()
.managerSelectedActivity
.activitySelected
.first
.activityInfo
.altitudeMin -
2;
final lineBarsData = [
LineChartBarData(
@ -57,7 +69,15 @@ class _MobileGraphAltitudeByTime extends State<MobileGraphAltitudeByTime> {
titlesData: FlTitlesData(
leftTitles: const AxisTitles(),
topTitles: const AxisTitles(),
bottomTitles: const AxisTitles(),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 20,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 60,

@ -94,7 +94,7 @@ class _MobileGraphBpmAndSpeedByTime
getTooltipItems: (List<LineBarSpot> lineBarsSpot) {
return lineBarsSpot.map((lineBarSpot) {
return LineTooltipItem(
"Seconde ${lineBarSpot.x.toInt()} ",
"Seconde ${lineBarSpot.x.toInt() / 10} ",
const TextStyle(
color: Colors.white,
fontSize: 10,
@ -110,9 +110,19 @@ class _MobileGraphBpmAndSpeedByTime
maxY: 110,
titlesData: FlTitlesData(
show: true,
leftTitles: const AxisTitles(),
leftTitles: AxisTitles(
sideTitles: widget.func.rightTitles,
),
topTitles: const AxisTitles(),
bottomTitles: const AxisTitles(),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 20,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 70,

@ -61,7 +61,7 @@ class _MobileBpmByTime extends State<MobileBpmByTime> {
reservedSize: 20,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))}s");
return Text("${double.parse((value/10).toStringAsFixed(2))}s");
},
)),
rightTitles: AxisTitles(

@ -19,10 +19,22 @@ class WebGraphAltitudeByTime extends StatefulWidget {
class _WebGraphAltitudeByTime extends State<WebGraphAltitudeByTime> {
@override
Widget build(BuildContext context) {
final double maxY =
context.watch<User>().managerSelectedActivity.getMaxAltitude() + 2;
final double minY =
context.watch<User>().managerSelectedActivity.getMinAltitude() - 2;
final double maxY = context
.watch<User>()
.managerSelectedActivity
.activitySelected
.first
.activityInfo
.altitudeMax +
2;
final double minY = context
.watch<User>()
.managerSelectedActivity
.activitySelected
.first
.activityInfo
.altitudeMin -
2;
final lineBarsData = [
LineChartBarData(

@ -24,10 +24,9 @@ class _WebGraphBpmAndSpeedByTime extends State<WebGraphBpmAndSpeedByTime> {
Widget build(BuildContext context) {
final double maxY = widget.data.maxBPM + 2;
final double minY = widget.data.minBPM - 2;
final double maxX =
final double maxX =
widget.data.bpmSecondes[widget.data.bpmSecondes.length - 1].x;
const double minX = 0.0;
return Container(
padding: const EdgeInsets.only(left: 15),
height: widget.media.width * 0.20,
@ -104,37 +103,25 @@ class _WebGraphBpmAndSpeedByTime extends State<WebGraphBpmAndSpeedByTime> {
),
),
lineBarsData: widget.func.lineBarsData1,
minY: 0,
minY: -10,
maxY: 110,
titlesData: FlTitlesData(
show: true,
leftTitles: AxisTitles(
sideTitles: widget.func.rightTitles,
sideTitles: widget.func.leftTitles,
),
topTitles: const AxisTitles(),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 20,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse((value / 10).toStringAsFixed(2))}s");
},
)),
bottomTitles:AxisTitles(
sideTitles: widget.func.bottomTitles,
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 70,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text(
"${double.parse(value.toStringAsFixed(2))} BPM");
},
))),
sideTitles: widget.func.rightTitles,
),),
gridData: FlGridData(
drawVerticalLine: true,
drawHorizontalLine: true,
horizontalInterval: (maxY - minY) / 5,
verticalInterval: (maxX - minX) / 4,
verticalInterval: (maxX - minX) / 5 ,
getDrawingHorizontalLine: (value) {
return FlLine(
color: TColor.gray.withOpacity(0.15),

@ -1,15 +1,16 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/common_widget/graph/data_for_graph/func_bpm_by_time.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
class WebBpmByTime extends StatefulWidget {
final Size media;
final DataHomeView data;
final FuncBpmByTime func;
const WebBpmByTime(this.media, this.data, {Key? key}) : super(key: key);
const WebBpmByTime(this.media, this.data, this.func, {Key? key})
: super(key: key);
@override
State<WebBpmByTime> createState() => _WebBpmByTime();
@ -18,13 +19,6 @@ class WebBpmByTime extends StatefulWidget {
class _WebBpmByTime extends State<WebBpmByTime> {
@override
Widget build(BuildContext context) {
final double maxY =
context.watch<User>().managerSelectedActivity.getMaxBpm() + 2;
final double minY =
context.watch<User>().managerSelectedActivity.getMinBpm() - 2;
final double maxX =
widget.data.bpmSecondes[widget.data.bpmSecondes.length - 1].x;
const double minX = 0.0;
final lineBarsData = [
LineChartBarData(
spots: widget.data.bpmSecondes,
@ -41,16 +35,11 @@ class _WebBpmByTime extends State<WebBpmByTime> {
width: widget.media.width * 0.35,
child: LineChart(LineChartData(
lineBarsData: lineBarsData,
minY: widget.data.minBPM.toDouble() * 0.95,
borderData: FlBorderData(show: false),
maxY: maxY,
minY: minY,
maxX: maxX,
minX: minX,
gridData: FlGridData(
drawVerticalLine: true,
drawHorizontalLine: true,
horizontalInterval: (maxY - minY) / 5,
verticalInterval: (maxX - minX) / 4,
getDrawingHorizontalLine: (value) {
return FlLine(
color: TColor.gray.withOpacity(0.15),
@ -61,19 +50,19 @@ class _WebBpmByTime extends State<WebBpmByTime> {
leftTitles: const AxisTitles(),
topTitles: const AxisTitles(),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 20,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))}s");
},
)),
sideTitles: widget.func.bottomTitles,
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 70,
showTitles: true,
getTitlesWidget: (value, meta) {
return Text("${double.parse(value.toStringAsFixed(2))} BPM");
return Text("${double.parse(value.toStringAsFixed(2))} BPM",
style: TextStyle(
color: TColor.gray,
fontSize: 12,
),
textAlign: TextAlign.center);
},
)),
))));

@ -9,7 +9,7 @@ class Info extends StatelessWidget {
Widget build(BuildContext context) {
String distance = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getTotalDistance()
.getDistanceAllActivitySelected()
.toString();
return Row(

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/view/home/notification_view.dart';
class EnteteHomeView extends StatelessWidget {
@ -18,7 +20,7 @@ class EnteteHomeView extends StatelessWidget {
style: TextStyle(color: TColor.gray, fontSize: 12),
),
Text(
"Benjelloun Othmane",
context.watch<User>().username,
style: TextStyle(
color: TColor.black,
fontSize: 20,

@ -10,15 +10,18 @@ class Stats extends StatelessWidget {
Widget build(BuildContext context) {
String calories = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getCalorie()
.getCalorieAllActivitySelected()
.toString();
String heartrate = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getAvgBpm()
.activitySelected
.first
.activityInfo
.bpmAvg
.toString();
String time = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getTotalTime()
.getTimeAllActivitySelected()
.toString();
return Column(
children: [
@ -127,6 +130,7 @@ class InfoStat extends StatelessWidget {
icon: icon,
iconColor: iconColor,
iconBackground: iconBackground,
sizeIcon: 8.0,
),
Align(
alignment: Alignment.bottomLeft,
@ -160,11 +164,13 @@ class StatIcon extends StatelessWidget {
required this.icon,
required this.iconColor,
required this.iconBackground,
required this.sizeIcon,
}) : super(key: key);
final IconData icon;
final Color iconColor;
final Color iconBackground;
final double? sizeIcon;
@override
Widget build(BuildContext context) {
@ -174,7 +180,7 @@ class StatIcon extends StatelessWidget {
color: iconBackground,
borderRadius: BorderRadius.circular(9),
),
child: Icon(icon, size: 8, color: iconColor),
child: Icon(icon, size: sizeIcon, color: iconColor),
);
}
}

@ -9,7 +9,7 @@ class Steps extends StatelessWidget {
Widget build(BuildContext context) {
String steps = Provider.of<User>(context, listen: false)
.managerSelectedActivity
.getTotalSteps()
.getTimeAllActivitySelected()
.toString();
return Padding(

@ -1,11 +1,11 @@
import 'package:flutter/foundation.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
class ActivityOfUser {
final ActivityInfo _activityInfo;
// A afficher
late String _categorie;
late String _date;
late String _fileUuid;
late String _nameFile;
final String _categorie;
final String _fileUuid;
final String _nameFile;
// ------------ //
late String _imageName;
@ -14,8 +14,8 @@ class ActivityOfUser {
String get fileUuid => _fileUuid;
String get nameFile => _nameFile;
String get categorie => _categorie;
String get date => _date;
String get category => _categorie;
ActivityInfo get activityInfo => _activityInfo;
Map<String, int> get enteteCSV => _enteteCSV;
// -- Getter/Setter -- Ancien //
@ -29,14 +29,9 @@ class ActivityOfUser {
}
ActivityOfUser(
String date, String categorie, String fileUuid, String nameFile) {
_categorie = categorie;
_date = date;
_fileUuid = fileUuid;
_nameFile = nameFile;
this._activityInfo, this._categorie, this._fileUuid, this._nameFile) {
// Mettre dans une fonction appart
if (categorie == "Walking") {
if (_categorie == "Walking") {
_imageName = "assets/img/workout1.svg";
} else {
// Mettre des conditions pour d'autre type d'activité
@ -46,7 +41,19 @@ class ActivityOfUser {
// -------------------------- FIN Localisation ---------------------- //
Map<String, dynamic> toMap() {
return {'categorie': _categorie, 'image': _imageName, 'date': _date};
Map<String, dynamic> toMapGeneric() {
Map<String, dynamic> map = {
'categorie': _categorie,
'image': _imageName,
'date': _activityInfo.startTime,
'time': _activityInfo.timeOfActivity,
};
return map;
}
Map<String, dynamic> toMapWalking() {
Map<String, dynamic> map = toMapGeneric();
map.addAll(activityInfo.toMapWalking());
return map;
}
}

@ -0,0 +1,227 @@
import 'dart:convert';
import 'package:smartfit_app_mobile/modele/manager_file.dart';
class ActivityInfo {
ManagerFile managerFile = ManagerFile();
ActivityInfo();
// -- Time -- // Ne pas calculer (Ligne session)
DateTime startTime = DateTime.now();
double timeOfActivity = 0.0;
double distance = 0.0;
int calories = 0;
int steps = 0;
// ----------- BPM ------------ //
int bpmMax = 0;
int bpmMin = 300;
int bpmAvg = 0;
// ----------- Denivelé ------------ //
double denivelePositif = 0.0;
double deniveleNegatif = 0.0;
// ----------- Altitude ------------ //
double altitudeMax = 0.0;
double altitudeMin = 30000.0;
double altitudeAvg = 0.0;
// ----------- Température --------- //
int temperatureMax = 0;
int temperatureMin = 3000;
int temperatureAvg = 0;
// ----------- Vitesse ------------- //
double vitesseMax = 0.0;
double vitesseMin = 999999.0;
double vitesseAvg = 0.0;
// ---------------------------------------------------------------------- //
// -- Fonction pour lire le csv et remplir la classe -- //
ActivityInfo getData(List<List<String>> csv) {
// - Entete - //
Map<String, int> enteteCSV = getEntete(csv.first);
// ------------- Var tmp ---------- //
// -- BPM -- //
int bpmSomme = 0;
int bpmNb = 0;
// -- Denivelé -- //
double lastDenivele = 0.0;
// -- Altitude -- //
double altitudeSomme = 0;
int alititudeNb = 0;
// -- Température -- //
int temperatureSomme = 0;
int temperatureNb = 0;
// -- Vitesse -- //
double vitesseSomme = 0.0;
int vitesseNb = 0;
// --- Boucle -- //
for (int i = 1; i < csv.length; i++) {
//
// ---------------------- BPM ---------------------- //
if (!isNull(enteteCSV["Value_${managerFile.fielBPM}"]!, csv[i])) {
int value =
int.parse(csv[i][enteteCSV["Value_${managerFile.fielBPM}"]!]);
bpmSomme += value;
bpmNb += 1;
if (value > bpmMax) {
bpmMax = value;
}
if (value < bpmMin) {
bpmMin = value;
}
}
/// ------------------ Denivele et Altitude --------------- //
if (!isNull(enteteCSV["Value_${managerFile.fieldAltitude}"]!, csv[i])) {
double value = double.parse(
csv[i][enteteCSV["Value_${managerFile.fieldAltitude}"]!]);
// -- Denivelé -- //
if (value > lastDenivele) {
denivelePositif += value - lastDenivele;
} else {
deniveleNegatif += (value - lastDenivele) * -1;
}
lastDenivele = value;
// -- Altitude -- //
if (value > altitudeMax) {
altitudeMax = value;
}
if (value < altitudeMin) {
altitudeMin = value;
}
altitudeSomme += value;
alititudeNb += 1;
}
// ------------------------ Température ----------------------- //
if (!isNull(
enteteCSV["Value_${managerFile.fieldTemperature}"]!, csv[i])) {
int value = int.parse(
csv[i][enteteCSV["Value_${managerFile.fieldTemperature}"]!]);
temperatureSomme += value;
temperatureNb += 1;
if (value > temperatureMax) {
temperatureMax = value;
}
if (value < temperatureMin) {
temperatureMin = value;
}
}
// ------------------------ Vitesse -----------------------------//
if (!isNull(enteteCSV["Value_${managerFile.fieldSpeed}"]!, csv[i])) {
double value =
double.parse(csv[i][enteteCSV["Value_${managerFile.fieldSpeed}"]!]);
vitesseSomme += value;
vitesseNb += 1;
if (value > vitesseMax) {
vitesseMax = value;
}
if (value < vitesseMin) {
vitesseMin = value;
}
}
}
// -- BPM -- //
bpmAvg = bpmSomme ~/ bpmNb;
// -- Atitude -- //
altitudeAvg = altitudeSomme / alititudeNb;
// -- Température -- //
temperatureAvg = temperatureSomme ~/ temperatureNb;
// -- Vitesse -- //
vitesseAvg = vitesseSomme / vitesseNb;
return this;
}
// ------------ Fonction utile ------------------- //
Map<String, int> getEntete(List<dynamic> content) {
Map<String, int> enteteCSV = {};
for (int i = 0; i < content.length; i++) {
enteteCSV.addAll({content[i]: i});
}
return enteteCSV;
}
bool isNull(int colonne, List<dynamic> ligne) {
return ligne[colonne] == "null";
}
// ------------- Pour print ----------------- //
Map<String, dynamic> toMapWalking() {
return {
// -- Denivelé -- //
"DenivelePositif": denivelePositif,
"DeniveleNegatif": denivelePositif,
// -- Altitude -- //
"AltitudeMax": altitudeMax,
"AltitudeMin": altitudeMin,
"AltitudeAvg": altitudeAvg
};
}
// --------------- JSON --------- //
// -- Lecture -- //
ActivityInfo.fromJson(Map<String, dynamic>? map) {
if (map == null) {
return;
}
// -- Ligne session -- //
startTime = DateTime.parse(map["startTime"]);
timeOfActivity = map["timeOfActivity"].toDouble();
distance = map["distance"].toDouble();
calories = map["calories"].toInt();
steps = map["steps"].toInt();
// -- BPM -- //
bpmAvg = map["bpmAvg"];
bpmMax = map["bpmMax"];
bpmMin = map["bpmMin"];
// -- Denivelé -- //
deniveleNegatif = map["deniveleNegatif"].toDouble();
denivelePositif = map["denivelePositif"].toDouble();
// -- Altitude -- //
altitudeMax = map["altitudeMax"].toDouble();
altitudeMin = map["altitudeMin"].toDouble();
altitudeAvg = map["altitudeAvg"].toDouble();
// -- Température -- //
temperatureMax = map["temperatureMax"].toInt();
temperatureMin = map["temperatureMin"].toInt();
temperatureAvg = map["temperatureAvg"].toInt();
// -- Vitesse -- //
vitesseMax = map["vitesseMax"].toDouble();
vitesseMin = map["vitesseMin"].toDouble();
vitesseAvg = map["vitesseAvg"].toDouble();
}
// -- Ecriture -- //
String toJson() {
Map<String, dynamic> jsonMap = {
// -- BPM -- //
'bpmAvg': bpmAvg,
'bpmMax': bpmMax,
'bpmMin': bpmMin,
// -- Denivelé -- //
'denivelePositif': denivelePositif,
'deniveleNegatif': deniveleNegatif,
// -- Altitude -- //
'altitudeMax': altitudeMax,
'altitudeMin': altitudeMin,
'altitudeAvg': altitudeAvg,
// -- Température -- //
'temperatureMax': temperatureMax,
'temperatureMin': temperatureMin,
'temperatureAvg': temperatureAvg,
// -- Vitesse -- //
'vitesseMax': vitesseMax,
'vitesseMin': vitesseMin,
'vitesseAvg': vitesseAvg,
// Ligne session
'startTime': startTime.toString(),
'timeOfActivity': timeOfActivity,
'distance': distance,
'calories': calories,
'steps': steps
};
return jsonEncode(jsonMap);
}
}

@ -1,5 +1,6 @@
import 'dart:typed_data';
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/request_api.dart';
import 'package:smartfit_app_mobile/modele/local_db/request_local.dart';
@ -157,13 +158,14 @@ class ApiWrapper {
Uint8List contentFile,
String filename,
String category,
String date,
DateTime date,
ActivityInfo activityInfo,
InfoMessage infoManager) async {
await init();
if (handleOffline(infoManager)) return const Tuple2(false, "offline");
Tuple2<bool, String> res =
await api.uploadFileByte(token, contentFile, filename, category, date);
Tuple2<bool, String> res = await api.uploadFileByte(
token, contentFile, filename, category, date, activityInfo);
stdout.write("uploadFileByte: ${res.item1}");
return res;
}

@ -1,6 +1,7 @@
import 'dart:io';
import 'dart:typed_data';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:tuple/tuple.dart';
abstract class IDataStrategy {
@ -21,8 +22,13 @@ abstract class IDataStrategy {
Future<Tuple2<bool, String>> uploadFile(String token, File file);
// Upload file as bytes
Future<Tuple2<bool, String>> uploadFileByte(String token,
Uint8List contentFile, String nameFile, String category, String date);
Future<Tuple2<bool, String>> uploadFileByte(
String token,
Uint8List contentFile,
String nameFile,
String category,
DateTime date,
ActivityInfo activityInfo);
// Get one file by id (LOCAL OK)
Future<Tuple2> getFile(String token, String fileUuid);

@ -2,11 +2,12 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:http/http.dart' as http;
import 'package:tuple/tuple.dart';
class RequestApi extends IDataStrategy {
class RequestApi implements IDataStrategy {
// Faire attention au URL
String urlApi =
"https://codefirst.iut.uca.fr/containers/SmartFit-smartfit_api";
@ -191,7 +192,8 @@ class RequestApi extends IDataStrategy {
Uint8List contentFile,
String nameFile,
String category,
String date) async {
DateTime date,
ActivityInfo activityInfo) async {
final uri = Uri.parse('$urlApi/user/files');
Map<String, String> headers = {'Authorization': token};
@ -204,7 +206,8 @@ class RequestApi extends IDataStrategy {
request.files.add(httpImage);
request.headers.addAll(headers);
request.fields["SmartFit_Category"] = category;
request.fields["SmartFit_Date"] = date;
request.fields["SmartFit_Date"] = date.toString();
request.fields["info"] = activityInfo.toJson();
final response = await request.send();

@ -19,9 +19,7 @@ class Activity {
String uuid;
String filename;
String category;
DateTime date;
String info;
Activity(
this.id, this.uuid, this.filename, this.category, this.date, this.info);
Activity(this.id, this.uuid, this.filename, this.category, this.info);
}

@ -4,6 +4,7 @@ import 'dart:typed_data';
import 'package:csv/csv.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/objectbox.g.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
@ -106,8 +107,9 @@ class ObjectBox {
List<ActivityOfUser> userActivityList = List.empty(growable: true);
for (Activity act in activityDBList) {
userActivityList.add(ActivityOfUser(
act.date.toString(), act.category, act.uuid, act.filename));
ActivityInfo actInfo = ActivityInfo.fromJson(jsonDecode(act.info));
userActivityList
.add(ActivityOfUser(actInfo, act.category, act.uuid, act.filename));
}
return userActivityList;

@ -1,4 +1,5 @@
import 'dart:convert';
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/local_db/model.dart';
import 'package:tuple/tuple.dart';
@ -30,7 +31,6 @@ class RequestLocal implements IDataStrategy {
"uuid": act.uuid,
"filename": act.filename,
"category": act.category,
"creation_date": act.date,
"info": act.info
};
jsonList.add(json);
@ -72,7 +72,8 @@ class RequestLocal implements IDataStrategy {
Uint8List contentFile,
String nameFile,
String category,
String date) async {
DateTime date,
ActivityInfo activityInfo) async {
return const Tuple2(false, "not implemented");
}

@ -2,6 +2,9 @@ import 'dart:convert';
import 'dart:typed_data';
import 'package:csv/csv.dart';
import 'package:fit_tool/fit_tool.dart';
import 'package:path_provider/path_provider.dart';
import 'package:smartfit_app_mobile/modele/activity_info/activity_info.dart';
import 'package:tuple/tuple.dart';
class ManagerFile {
// -- Field
@ -12,8 +15,17 @@ class ManagerFile {
final String _fieldBPM = "heart_rate";
final String _fieldSpeed = "speed";
final String _fieldAltitude = "altitude";
final String _fieldTotalStep = "total_strides";
final String _fieldTotalCalorie = "total_calories";
final String _fieldTemperature = "temperature";
// -- Not in CSV (Ligne session) -- //
static const String _session = "session";
static const String _startTime = "start_time";
static const String _sport = "sport";
static const String _timeActivity = "total_elapsed_time";
static const String _totalDistance = "total_distance";
static const String _totalCalories = "total_calories";
static const String _totalStep = "total_strides";
// -- Getter field
String get fieldTimeStamp => _fieldTimestamp;
String get fieldPositionLatitude => _fieldPositionLatitue;
@ -22,10 +34,20 @@ class ManagerFile {
String get fielBPM => _fieldBPM;
String get fieldSpeed => _fieldSpeed;
String get fieldAltitude => _fieldAltitude;
String get fieldTotalStep => _fieldTotalStep;
String get fieldTotalCalories => _fieldTotalCalorie;
String get fieldTemperature => _fieldTemperature;
// -- Categorie -- //
static const String _generic = "generic";
static const String _velo = "cycling";
static const String _marche = "walking";
// -- Getter categorie
String get marche => _marche;
String get generic => _generic;
List<String> allowedFieldWalking = List.empty(growable: true);
List<String> allowedFieldGeneric = List.empty(growable: true);
List<String> allowedFieldCycling = List.empty(growable: true);
ManagerFile() {
allowedFieldWalking = [
@ -36,29 +58,132 @@ class ManagerFile {
_fieldBPM,
_fieldSpeed,
_fieldAltitude,
_fieldTotalStep,
_fieldTotalCalorie
_fieldTemperature
];
allowedFieldGeneric = [_fieldTimestamp, _fieldBPM];
allowedFieldCycling = [
_fieldTimestamp,
_fieldPositionLatitue,
_fieldPositionLongitude,
_fieldDistance,
_fieldBPM,
_fieldSpeed,
_fieldAltitude,
_fieldTemperature
];
}
// -- 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 _velo;
case 11:
return _marche;
default:
return _generic;
}
}
// ------------- Get The path of application --- //
Future<String> get localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Tuple4<bool, List<List<String>>, ActivityInfo, String>
convertBytesFitFileIntoCSVListAndGetInfo(Uint8List bytes) {
List<Record> fitFile = FitFile.fromBytes(bytes).records;
String categorie;
List<String> fieldAllowed = [];
ActivityInfo info = ActivityInfo();
// -- Chercher ligne session -- //
List<dynamic> ligneSession = _getLigneSession(fitFile);
if (ligneSession.isEmpty) {
return Tuple4(false, List.empty(), ActivityInfo(), "");
}
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;
break;
case (_generic):
fieldAllowed = allowedFieldGeneric;
break;
default:
// A REMETRE EN GENERIC
//fieldAllowed = allowedFieldGeneric;
//info = ActivityInfoGeneric();
//categorie = _generic;
fieldAllowed = allowedFieldWalking;
break;
}
// -------- Transformation en CSV ----------- //
List<List<String>> csvData = transformDataMapIntoCSV(
getDataOfListeOfRecord(fitFile, fieldAllowed), fieldAllowed);
// ------ Remplir info avec la ligne session --------- //
info.startTime = DateTime.fromMillisecondsSinceEpoch(
int.parse(_getXfromListe(_startTime, ligneSession)));
info.timeOfActivity =
double.parse(_getXfromListe(_timeActivity, ligneSession));
info.distance = double.parse(_getXfromListe(_totalDistance, ligneSession));
info.calories = int.parse(_getXfromListe(_totalCalories, ligneSession));
info.steps = int.parse(_getXfromListe(_totalStep, ligneSession));
// ----------------------------------------------------- //
return Tuple4(true, csvData, info.getData(csvData), categorie);
}
List<List<String>> convertBytesFitFileIntoCSVList(Uint8List bytes) {
FitFile fitFile = FitFile.fromBytes(bytes);
List<dynamic> _getLigneSession(List<Record> listRecord) {
for (int i = listRecord.length - 1; i != listRecord.length - 5; i--) {
List<dynamic> tmpListe = listRecord[i].toRow();
if (tmpListe[0] == "Data" && tmpListe[2] == _session) {
return tmpListe;
}
}
return List.empty();
}
String _getXfromListe(String x, List<dynamic> liste) {
for (int i = 0; i < liste.length; i++) {
if (liste[i] == x) {
return liste[i + 1].toString();
}
}
return "null";
}
// ----------- Lire le fit et extarire les données qu'on choisi ----------- //
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 fitFile.records) {
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 (allowedFieldWalking.contains(listeField[i])) {
if (allowedField.contains(listeField[i])) {
Map<String, String> tmp = {};
tmp["Value"] = listeField[i + 1].toString();
tmp["Unite"] = listeField[i + 2].toString();
@ -66,27 +191,33 @@ class ManagerFile {
i += 2;
skip = false;
}
// -- Pour boucler -- //
i += 1;
}
if (!skip) {
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 de l'entête -- //
List<String> enteteCSV = [];
for (String field in allowedFieldWalking) {
for (String field in fieldAllowed) {
enteteCSV.add("Value_$field");
enteteCSV.add("Unite_$field");
}
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);
for (String field in allowedFieldWalking) {
for (String field in fieldAllowed) {
if (!ligne.containsKey(field)) {
tmpLigne.add("null");
tmpLigne.add("null");
@ -101,82 +232,4 @@ class ManagerFile {
// ------- FIN --------------- //
return csvData;
}
// -- Read the byte of file CSV -- //
List<List<dynamic>> convertByteIntoCSV(Uint8List bytes) {
return const CsvToListConverter().convert(utf8.decode(bytes));
}
/*
// ------------- 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);*/
}

@ -3,19 +3,17 @@ import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:smartfit_app_mobile/common_widget/graph/graph.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:latlong2/latlong.dart' as osm;
class ManagerSelectedActivity {
final ManagerFile _managerFile = ManagerFile();
List<ActivityOfUser> activitySelected = List.empty(growable: true);
bool addSelectedActivity(ActivityOfUser activityOfUser) {
// Regarder si l'entete est la même
// C'est de la merde!!
/*
if (activitySelected.isNotEmpty &&
activitySelected.first.enteteCSV != activityOfUser.enteteCSV) {
activityOfUser.category != activitySelected.first.category) {
return false;
}*/
}
activitySelected.add(activityOfUser);
return true;
}
@ -54,7 +52,6 @@ class ManagerSelectedActivity {
List<FlSpot> getXWithTime(String field) {
List<FlSpot> result = List.empty(growable: true);
int firstTimestamp = 0;
for (int c = 0; c < activitySelected.length; c++) {
@ -82,208 +79,141 @@ class ManagerSelectedActivity {
return result;
}
// ----------------- BPM ------------------ //
//-------------------------------------------------------------------------------------------//
// Retourne le BPM Max (Fichier CSV)
int getMaxBpm() {
// ----------------- BPM ------------------ //
int getBpmMaxAllActivitieSelected() {
int max = 0;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(c, i,
activitySelected[c].enteteCSV["Value_${_managerFile.fielBPM}"]!)) {
int valueTmp = activitySelected[c].contentActivity[i]
[activitySelected[c].enteteCSV["Value_${_managerFile.fielBPM}"]!];
if (valueTmp > max) {
max = valueTmp;
}
}
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.bpmMax > max) {
max = activityOfUser.activityInfo.bpmMax;
}
}
return max;
}
// Retourne le BPM Min (Fichier CSV)
int getMinBpm() {
int min = 300;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(c, i,
activitySelected[c].enteteCSV["Value_${_managerFile.fielBPM}"]!)) {
int valueTmp = activitySelected[c].contentActivity[i]
[activitySelected[c].enteteCSV["Value_${_managerFile.fielBPM}"]!];
if (valueTmp < min) {
min = valueTmp;
}
}
int getBpmMinAllActivitieSelected() {
int min = 999;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.bpmMax < min) {
min = activityOfUser.activityInfo.bpmMin;
}
}
return min;
}
// Retourne le BPM avg (Fichier CSV)
int getAvgBpm() {
int getBpmAvgAllActivitieSelected() {
int somme = 0;
int nb = 0;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(c, i,
activitySelected[c].enteteCSV["Value_${_managerFile.fielBPM}"]!)) {
somme += activitySelected[c].contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fielBPM}"]!] as int;
nb++;
}
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.bpmAvg;
}
return somme ~/ activitySelected.length;
}
// ------------------ Fin BPM ------------------- //
// ------------------ Altitude ------------------ //
double getMaxAltitudeAllActivitySelected() {
double max = 0.0;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.altitudeMax > max) {
max = activityOfUser.activityInfo.altitudeMax;
}
}
return somme ~/ nb;
return max;
}
// -------------------------- FIN BPM ---------------------- //
double getMinAltitudeAllActivitySelected() {
double min = 99999.0;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.altitudeMax < min) {
min = activityOfUser.activityInfo.altitudeMin;
}
}
return min;
}
// ---------------------- Distance ---------------------- //
double getAvgAltitudeAllActivitySelected() {
double somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.altitudeAvg;
}
return somme / activitySelected.length;
}
// ------------------ Fin Altitude ------------------- //
double getTotalDistance() {
double max = 0;
// ------------------ Température -------------------- //
int getAvgTemperatureAllActivitySelected() {
int somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.temperatureAvg;
}
return somme ~/ activitySelected.length;
}
for (int c = 0; c < activitySelected.length; c++) {
for (int i = activitySelected[c].contentActivity.length - 1;
i != 0;
i--) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldDistance}"]!)) {
double valueTmp = activitySelected[c]
.contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldDistance}"]!]
.toDouble();
if (valueTmp > max) {
max = valueTmp;
}
}
int getMaxTemperatureAllActivitySelected() {
int max = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.temperatureMax > max) {
max = activityOfUser.activityInfo.temperatureMax;
}
}
return max;
}
// ---------------------- FIN Distance ---------------------- //
// ---------------------- Calories ---------------------- //
int getCalorie() {
for (int c = 0; c < activitySelected.length; c++) {
for (int i = activitySelected[c].contentActivity.length - 1;
i != 0;
i--) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTotalCalories}"]!)) {
return activitySelected[c].contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTotalCalories}"]!] as int;
}
int getMinTemperatureAllActivitySelected() {
int min = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.temperatureMin > min) {
min = activityOfUser.activityInfo.temperatureMin;
}
}
return 0;
return min;
}
// -------------------------- FIN Température ---------------------- //
// ---------------------- FIN Calories ---------------------- //
// ---------------------- Step ------------------------------//
// ---------------------- Distance ---------------------- //
int getTotalSteps() {
for (int c = 0; c < activitySelected.length; c++) {
for (int i = activitySelected[c].contentActivity.length - 1;
i != 0;
i--) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTotalStep}"]!)) {
return activitySelected[c]
.contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTotalStep}"]!]
.toInt();
}
}
double getDistanceAllActivitySelected() {
double somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.distance;
}
return 0;
return somme;
}
// ----------------------- FIN Step ------------------------ //
// ------------------------- Time ----------------------------- //
// ---------------------- FIN Distance ---------------------- //
int getTotalTime() {
for (int c = 0; c < activitySelected.length; c++) {
for (int i = activitySelected[c].contentActivity.length - 1;
i != 0;
i--) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTimeStamp}"]!)) {
return activitySelected[c].contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldTimeStamp}"]!];
}
}
// ---------------------- Calories ---------------------- //
int getCalorieAllActivitySelected() {
int somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.calories;
}
return 0;
return somme;
}
// ---------------------------- FIN time -------------------- //
// ---------------------------------------- Altitude -------------------- //
// ---------------------- FIN Calories ---------------------- //
// ---------------------- Step ------------------------------//
// --- Fichier CSV --- //
double getMaxAltitude() {
double max = 0;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldAltitude}"]!)) {
double valueTmp = activitySelected[c]
.contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldAltitude}"]!]
.toDouble();
if (valueTmp > max) {
max = valueTmp;
}
}
}
int getStepsAllActivitySelected() {
int somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.steps;
}
return max;
return somme;
}
// ----------------------- FIN Step ------------------------ //
// --- Fichier CSV --- //
double getMinAltitude() {
double min = 5000;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldAltitude}"]!)) {
double valueTmp = activitySelected[c]
.contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldAltitude}"]!]
.toDouble();
if (valueTmp < min) {
min = valueTmp;
}
}
}
// ------------------------- Time ----------------------------- //
double getTimeAllActivitySelected() {
double somme = 0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.timeOfActivity;
}
return min;
return somme;
}
// -------------------------- FIN altitude ---------------------- //
// ---------------------------- FIN time -------------------- //
// -------------------------- Speed ---------------------- //
@ -326,50 +256,32 @@ class ManagerSelectedActivity {
return result;
}
// Retourne la Speed Max (Fichier CSV)
double getMaxSpeed() {
double getMaxSpeedAllActivitySelected() {
double max = 0.00;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldSpeed}"]!)) {
double valueTmp = activitySelected[c]
.contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldSpeed}"]!]
.toDouble();
if (valueTmp > max) {
max = valueTmp;
}
}
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.vitesseMax > max) {
max = activityOfUser.activityInfo.vitesseMax;
}
}
return max;
}
// Retourne avg Max (Fichier CSV)
double getAvgSpeed() {
double somme = 0;
int nb = 0;
for (int c = 0; c < activitySelected.length; c++) {
for (int i = 0; i < activitySelected[c].contentActivity.length; i++) {
if (_notNull(
c,
i,
activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldSpeed}"]!)) {
somme += activitySelected[c].contentActivity[i][activitySelected[c]
.enteteCSV["Value_${_managerFile.fieldSpeed}"]!];
nb++;
}
double getMinSpeedAllActivitySelected() {
double min = 99999.9;
for (ActivityOfUser activityOfUser in activitySelected) {
if (activityOfUser.activityInfo.vitesseMin < min) {
min = activityOfUser.activityInfo.vitesseMin;
}
}
return min;
}
return somme / nb;
double getAvgSpeedAllActivitySelected() {
double somme = 0.0;
for (ActivityOfUser activityOfUser in activitySelected) {
somme += activityOfUser.activityInfo.vitesseAvg;
}
return somme / activitySelected.length;
}
// -------------------------- FIN Speed ---------------------- //
@ -401,4 +313,28 @@ class ManagerSelectedActivity {
}
return list;
}
List<osm.LatLng> getPositionOSM() {
List<osm.LatLng> list = List.empty(growable: true);
for (int i = 0; i < activitySelected[0].contentActivity.length; i++) {
if (_notNull(
0,
i,
activitySelected[0]
.enteteCSV["Value_${_managerFile.fieldPositionLatitude}"]!) &&
_notNull(
0,
i,
activitySelected[0].enteteCSV[
"Value_${_managerFile.fieldPositionLongitude}"]!)) {
list.add(osm.LatLng(
activitySelected[0].contentActivity[i][activitySelected[0]
.enteteCSV["Value_${_managerFile.fieldPositionLatitude}"]!],
activitySelected[0].contentActivity[i][activitySelected[0]
.enteteCSV["Value_${_managerFile.fieldPositionLongitude}"]!]));
}
}
return list;
}
}

@ -24,4 +24,32 @@ class User extends ChangeNotifier {
listActivity.insert(index, activity);
notifyListeners();
}
// ------------ Fonction Calcul -------- //
// --- Time --- //
double getTotalTimeAllActivity() {
double totalTime = 0.0;
for (ActivityOfUser activity in listActivity) {
totalTime += activity.activityInfo.timeOfActivity;
}
return totalTime;
}
// ------------ Walking -------------- //
// ---- Denivelé ---- //
double getTotalDenivelePositif() {
double totalDevPos = 0.0;
for (ActivityOfUser activity in listActivity) {
totalDevPos += activity.activityInfo.denivelePositif;
}
return totalDevPos;
}
double getTotalDeniveleNegatif() {
double totalDevNeg = 0.0;
for (ActivityOfUser activity in listActivity) {
totalDevNeg += activity.activityInfo.deniveleNegatif;
}
return totalDevNeg;
}
}

@ -7,6 +7,8 @@ class DataHomeView {
late List<FlSpot> altitudeSeconde;
int minBPM = 0;
int maxBPM = 0;
double maxSpeed = 0;
double time = 0;
DataHomeView(this.bpmSecondes, this.bpmSecondes2, this.vitesseSecondes,
this.altitudeSeconde);

@ -21,8 +21,8 @@ class HomeViewUtil {
List<FlSpot> bpmSecondes2 = List.from(bpmSecondes);
return DataHomeView(bpmSecondes, normaliserDeuxiemeElement(bpmSecondes2),
normaliserDeuxiemeElement(vitesseSecondes), altitudeSeconde);
return DataHomeView(normaliserPremierElement(bpmSecondes), normaliserPremierElement(normaliserDeuxiemeElement(bpmSecondes2)),
normaliserPremierElement(normaliserDeuxiemeElement(vitesseSecondes)), altitudeSeconde);
}
List<FlSpot> normaliserDeuxiemeElement(List<FlSpot> liste) {
@ -41,4 +41,21 @@ class HomeViewUtil {
}
return liste;
}
List<FlSpot> normaliserPremierElement(List<FlSpot> 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;
}
}
// 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;
}
}

@ -10,6 +10,9 @@ import 'package:csv/csv.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_info/activity_info.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/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
@ -34,9 +37,11 @@ class ListActivityUtile {
// TODO: Not sure this line as an utility
// localDB.saveActivityFile(activityOfUser.contentActivity);
Provider.of<User>(context, listen: false)
if (!Provider.of<User>(context, listen: false)
.managerSelectedActivity
.addSelectedActivity(activityOfUser);
.addSelectedActivity(activityOfUser)) {
return const Tuple2(false, "Pas de même categorie");
}
return const Tuple2(true, "Yeah");
}
@ -54,8 +59,10 @@ class ListActivityUtile {
Provider.of<User>(context, listen: false).listActivity.clear();
notZero = true;
}
// -- connaitre le type de categorie pour changer le type d'info -- //
Provider.of<User>(context, listen: false).addActivity(ActivityOfUser(
element["creation_date"].toString(),
ActivityInfo.fromJson(element["info"]),
element["category"].toString(),
element["uuid"].toString(),
element["filename"].toString()));
@ -66,22 +73,19 @@ class ListActivityUtile {
element["uuid"],
element["filename"],
element["category"],
DateTime.parse(element["creation_date"]),
element["info"]
.toString())); // Do not remove toString(), it do not work w/o it, idk why
.toString())); // TODO: Do not remove toString(), it do not work w/o it, idk why
}
/*
if (notZero) {
await getContentActivity(context);
}*/
return const Tuple2(true, "Yeah");
}
Future<Tuple2<bool, String>> addFile(Uint8List bytes, String filename,
Future<Tuple2<bool, String>> _addFile(Uint8List bytes, String filename,
String token, InfoMessage infoManager) async {
// -- Transormer le fit en CSV
List<List<String>> csv = _managerFile.convertBytesFitFileIntoCSVList(bytes);
String csvString = const ListToCsvConverter().convert(csv);
Tuple4<bool, List<List<String>>, ActivityInfo, String> resultData =
_managerFile.convertBytesFitFileIntoCSVListAndGetInfo(bytes);
String csvString = const ListToCsvConverter().convert(resultData.item2);
Uint8List byteCSV = Uint8List.fromList(utf8.encode(csvString));
// Save on local storage if plateform not browser
@ -90,20 +94,42 @@ class ListActivityUtile {
actSaver.saveActivity(byteCSV, filename);
}
String categoryActivity = filename.split("_").first.toLowerCase();
String dateActivity = filename.split("_")[1].split("T").first;
Tuple2<bool, String> result = await api.uploadFileByte(
token, byteCSV, filename, categoryActivity, dateActivity, infoManager);
token,
byteCSV,
filename,
resultData.item4,
resultData.item3.startTime,
resultData.item3,
infoManager);
if (result.item1 == false) {
return Tuple2(false, result.item2);
}
return const Tuple2(true, "Yeah");
}
// --- Ne marche pas sous window !! Jsp linux (mettre en format mobile) -- //
void addFileWeb(Uint8List? bytes, String token, String filename,
BuildContext context, InfoMessage infoManager) async {
if (bytes == null) {
return;
}
Tuple2<bool, String> resultAdd =
await _addFile(bytes, filename, token, infoManager);
if (!resultAdd.item1) {
//print("Message error");
return;
}
Tuple2<bool, String> resultGet = await getFiles(token, context);
if (!resultGet.item1) {
//print("Message error");
return;
}
}
void addFileMobile(String path, String token, String filename,
BuildContext context, InfoMessage infoManager) async {
Tuple2<bool, String> resultAdd = await addFile(
Tuple2<bool, String> resultAdd = await _addFile(
await File(path).readAsBytes(), filename, token, infoManager);
if (!resultAdd.item1) {
//print("Message error");

@ -2,7 +2,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity.dart';
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
@ -15,7 +15,6 @@ class MobileListActivity extends StatefulWidget {
}
class _MobileListActivity extends State<MobileListActivity> {
FilePickerResult? result;
final ListActivityUtile _utile = ListActivityUtile();
final InfoMessage infoManager = InfoMessage();
@ -56,12 +55,12 @@ class _MobileListActivity extends State<MobileListActivity> {
onPressed: () async {
FilePickerResult? result =
await FilePicker.platform.pickFiles();
if (result != null) {
if (result != null && result.files.isNotEmpty) {
// ignore: use_build_context_synchronously
_utile.addFileMobile(
result.files.single.path!,
Provider.of<User>(context, listen: false).token,
result.files.single.name,
result.files.first.name,
context,
infoManager);
} else {
@ -98,7 +97,7 @@ class _MobileListActivity extends State<MobileListActivity> {
),
)
])
: const ListActivity(),
: const ListActivityWidget(),
SizedBox(
height: media.width * 0.1,
),

@ -1,10 +1,7 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/modele/utile/info_message.dart';
import 'package:smartfit_app_mobile/modele/utile/list_activity/list_activity_utile.dart';
import 'package:smartfit_app_mobile/view/activity/list_activity.dart';
import 'package:tuple/tuple.dart';
import 'package:universal_html/html.dart' as html;
import 'package:smartfit_app_mobile/common_widget/container/list/list_activity_widget.dart';
import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
@ -22,27 +19,6 @@ class _WebListActivityState extends State<WebListActivity> {
final ListActivityUtile _utile = ListActivityUtile();
final InfoMessage infoManager = InfoMessage();
void addFileWeb(html.File file, String token) async {
final reader = html.FileReader();
reader.readAsArrayBuffer(file);
reader.onLoadEnd.listen((event) async {
if (reader.readyState == html.FileReader.DONE) {
Uint8List bytes = reader.result as Uint8List;
Tuple2<bool, String> resultAdd =
await _utile.addFile(bytes, file.name, token, infoManager);
if (!resultAdd.item1) {
return;
}
Tuple2<bool, String> resultGet = await _utile.getFiles(token, context);
if (!resultGet.item1) {
//print("MessageError");
return;
}
}
});
}
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
@ -77,19 +53,20 @@ class _WebListActivityState extends State<WebListActivity> {
fontWeight: FontWeight.w700))),
TextButton(
onPressed: () async {
html.FileUploadInputElement uploadInput =
html.FileUploadInputElement();
uploadInput.click();
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
if (files != null && files.isNotEmpty) {
addFileWeb(
files[0],
Provider.of<User>(context, listen: false)
.token); // Lecture du fichier sélectionné
}
});
FilePickerResult? result =
await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) {
_utile.addFileWeb(
result.files.first.bytes,
Provider.of<User>(context, listen: false).token,
result.files.first.name,
context,
infoManager);
} else {
print("Picker");
// msg d'erreur
// User canceled the picker
}
},
child: Text(
"Ajouter",
@ -116,7 +93,7 @@ class _WebListActivityState extends State<WebListActivity> {
),
)
])
: const ListActivity(),
: const ListActivityWidget(),
SizedBox(
height: media.width * 0.1,
),

@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/view/home/mobile/mobile_homeview.dart';
import 'package:smartfit_app_mobile/view/home/no_activity_view.dart';
import 'package:smartfit_app_mobile/view/home/stats_activities_view.dart';
import 'package:smartfit_app_mobile/view/home/web/web_homeview.dart';
class HomeView extends StatefulWidget {
@ -17,25 +17,21 @@ class HomeView extends StatefulWidget {
class _HomeViewState extends State<HomeView> {
@override
Widget build(BuildContext context) {
List<ActivityOfUser> listSelected =
context.watch<User>().managerSelectedActivity.activitySelected;
if (listSelected.isEmpty) {
return ScreenTypeLayout.builder(
mobile: (_) => const NoActivityView("Pas d'activité sélectionnée"),
desktop: (_) => const NoActivityView("Pas d'activité sélectionnée"),
);
}
if (listSelected.length > 1) {
return ScreenTypeLayout.builder(
mobile: (_) => const NoActivityView(
"Qu'une seule activité doit être sélectionner"),
desktop: (_) => const NoActivityView(
"Qu'une seule activité doit être sélectionner"),
);
}
return ScreenTypeLayout.builder(
mobile: (_) => const MobileHomeView(),
desktop: (_) => const WebHomeView(),
);
final selectedActivitiesCount =
context.watch<User>().managerSelectedActivity.activitySelected.length;
return selectedActivitiesCount == 1
? ScreenTypeLayout.builder(
mobile: (_) => const MobileHomeView(),
desktop: (_) => const WebHomeView(),
)
: selectedActivitiesCount > 1
? const StatAtivities()
: ScreenTypeLayout.builder(
mobile: (_) =>
const NoActivityView("Pas d'activité sélectionnée"),
desktop: (_) =>
const NoActivityView("Pas d'activité sélectionnée"),
);
}
}

@ -30,17 +30,23 @@ class _MobileHomeView extends State<MobileHomeView> {
data = HomeViewUtil().initData(context);
// -- BPM -- //
data.maxBPM = managerSelectedActivity.getMaxBpm();
data.minBPM = managerSelectedActivity.getMinBpm();
int avgBpm = managerSelectedActivity.getAvgBpm();
data.maxBPM =
managerSelectedActivity.activitySelected.first.activityInfo.bpmMax;
data.minBPM =
managerSelectedActivity.activitySelected.first.activityInfo.bpmMin;
int avgBpm =
managerSelectedActivity.activitySelected.first.activityInfo.bpmAvg;
// -- Altitude -- //
double minAltitude = managerSelectedActivity.getMinAltitude();
double maxAltitude = managerSelectedActivity.getMaxAltitude();
double avgAltitude = (maxAltitude + minAltitude) / 2;
double minAltitude =
managerSelectedActivity.activitySelected.first.activityInfo.altitudeMin;
double maxAltitude =
managerSelectedActivity.activitySelected.first.activityInfo.altitudeMax;
double avgAltitude =
managerSelectedActivity.activitySelected.first.activityInfo.altitudeAvg;
// -- Speed -- //
double maxSpeed = managerSelectedActivity.getMaxSpeed();
double avgSpeed = managerSelectedActivity.getAvgSpeed();
double maxSpeed = managerSelectedActivity.getMaxSpeedAllActivitySelected();
double avgSpeed = managerSelectedActivity.getAvgSpeedAllActivitySelected();
return Scaffold(
backgroundColor: TColor.white,

@ -0,0 +1,235 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:smartfit_app_mobile/common_widget/container/container_stats_activities.dart';
import 'package:smartfit_app_mobile/common_widget/other/entete_home_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/manager_selected_activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/home_view_util.dart';
class StatAtivities extends StatefulWidget {
const StatAtivities({super.key});
@override
State<StatAtivities> createState() => _StatAtivities();
}
class _StatAtivities extends State<StatAtivities> {
late DataHomeView data;
TextEditingController bpmController = TextEditingController();
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
data = HomeViewUtil().initData(context);
ManagerSelectedActivity managerSelectedActivity =
context.watch<User>().managerSelectedActivity;
// -- BPM -- //
int maxBpm = managerSelectedActivity.getBpmMaxAllActivitieSelected();
int minBpm = managerSelectedActivity.getBpmMinAllActivitieSelected();
int avgBpm = managerSelectedActivity.getBpmAvgAllActivitieSelected();
// -- Altitude -- //
double maxAltitude =
managerSelectedActivity.getMaxAltitudeAllActivitySelected();
double minAltitude =
managerSelectedActivity.getMinAltitudeAllActivitySelected();
double avgAltitude =
managerSelectedActivity.getAvgAltitudeAllActivitySelected();
// -- Température -- //
double avgTemperature = context
.watch<User>()
.managerSelectedActivity
.getAvgTemperatureAllActivitySelected()
.toDouble();
double maxTemperature = context
.watch<User>()
.managerSelectedActivity
.getMaxTemperatureAllActivitySelected()
.toDouble();
double minTemperature = context
.watch<User>()
.managerSelectedActivity
.getMinTemperatureAllActivitySelected()
.toDouble();
// ----- Distance ---- //
double getTotalDistance = context
.watch<User>()
.managerSelectedActivity
.getDistanceAllActivitySelected();
// ---- Calories --- //
int totalCalories = context
.watch<User>()
.managerSelectedActivity
.getCalorieAllActivitySelected();
// --- Steps --- //
int totalSteps = context
.watch<User>()
.managerSelectedActivity
.getStepsAllActivitySelected();
// -- Time -- //
double totalTime = context
.watch<User>()
.managerSelectedActivity
.getTimeAllActivitySelected();
// -- Speed -- //
double avgSpeed = context
.watch<User>()
.managerSelectedActivity
.getAvgSpeedAllActivitySelected();
double maxSpeed = context
.watch<User>()
.managerSelectedActivity
.getMaxAltitudeAllActivitySelected();
double minSpeed = context
.watch<User>()
.managerSelectedActivity
.getMinAltitudeAllActivitySelected();
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: media.width * 0.03,
),
const EnteteHomeView(),
SizedBox(
height: media.width * 0.05,
),
Text(
"Status d'activité",
style: TextStyle(
color: TColor.black,
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$avgBpm BPM", "Moyenne Bpm", Icons.favorite),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$maxBpm BPM", "Maximum Bpm", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$minBpm BPM", "Minimum Bpm", Icons.trending_down)
],
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$avgSpeed m/s", "Moyenne vitesse", Icons.bolt),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$maxSpeed m/s", "Maximum vitesse", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$minSpeed m/s", "Minimum vitesse", Icons.trending_down)
],
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities("$avgTemperature °C",
"Moyenne Temperature", Icons.thermostat),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$maxTemperature °C",
"Maximum Temperature", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$minTemperature °C",
"Minimum Temperature", Icons.trending_down)
],
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$avgAltitude m", "Moyenne Altitude", Icons.landscape),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$maxAltitude m",
"Maximum Altitude", Icons.trending_up),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$minAltitude m",
"Minimum Altitude", Icons.trending_down)
],
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities("$getTotalDistance m",
"Distance Totale", Icons.double_arrow),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities(
"$totalSteps", "Total Pas", Icons.do_not_step_rounded),
],
),
SizedBox(
height: media.width * 0.03,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ContainerStatsActivities(
"$totalTime s", "Temps Total", Icons.timer),
SizedBox(
width: media.width * 0.03,
),
ContainerStatsActivities("$totalCalories kCal",
"Calories Dépensées", Icons.local_fire_department),
],
),
SizedBox(
height: media.width * 0.03,
),
],
),
),
),
),
);
}
}

@ -6,6 +6,7 @@ import 'package:smartfit_app_mobile/common_widget/graph/bpm_and_speed_by_time.da
import 'package:smartfit_app_mobile/common_widget/graph/bpm_by_time.dart';
import 'package:smartfit_app_mobile/common_widget/other/entete_home_view.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/manager_selected_activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/data_home_view.dart';
import 'package:smartfit_app_mobile/modele/utile/home_view/home_view_util.dart';
@ -24,24 +25,41 @@ class _WebHomeView extends State<WebHomeView> {
@override
Widget build(BuildContext context) {
var media = MediaQuery.of(context).size;
ManagerSelectedActivity managerSelectedActivity =
context.watch<User>().managerSelectedActivity;
// -- BPM -- //
int maxBpm = context.watch<User>().managerSelectedActivity.getMaxBpm();
int minBpm = context.watch<User>().managerSelectedActivity.getMinBpm();
int avgBpm = context.watch<User>().managerSelectedActivity.getAvgBpm();
int maxBpm =
managerSelectedActivity.activitySelected.first.activityInfo.bpmMax;
int minBpm =
managerSelectedActivity.activitySelected.first.activityInfo.bpmMin;
int avgBpm =
managerSelectedActivity.activitySelected.first.activityInfo.bpmAvg;
// -- Altitude -- //
double minAltitude =
context.watch<User>().managerSelectedActivity.getMinAltitude();
managerSelectedActivity.activitySelected.first.activityInfo.altitudeMin;
double maxAltitude =
context.watch<User>().managerSelectedActivity.getMaxAltitude();
double avgAltitude = (maxAltitude + minAltitude) / 2;
managerSelectedActivity.activitySelected.first.activityInfo.altitudeMax;
double avgAltitude =
managerSelectedActivity.activitySelected.first.activityInfo.altitudeAvg;
// -- Speed -- //
double maxSpeed =
context.watch<User>().managerSelectedActivity.getMaxSpeed();
double avgSpeed =
context.watch<User>().managerSelectedActivity.getAvgSpeed();
double maxSpeed = context
.watch<User>()
.managerSelectedActivity
.getMaxSpeedAllActivitySelected();
double avgSpeed = context
.watch<User>()
.managerSelectedActivity
.getAvgSpeedAllActivitySelected();
data = HomeViewUtil().initData(context);
data.maxBPM = maxBpm;
data.minBPM = minBpm;
data.maxSpeed = maxSpeed;
data.time = context
.watch<User>()
.managerSelectedActivity
.getTimeAllActivitySelected();
return Scaffold(
backgroundColor: TColor.white,
body: SingleChildScrollView(
@ -103,7 +121,7 @@ class _WebHomeView extends State<WebHomeView> {
fontWeight: FontWeight.w700),
),
SizedBox(
height: media.width * 0.02,
height: media.width * 0.03,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,

@ -50,34 +50,34 @@ class _WebMainTabViewState extends State<WebMainTabView> {
onTap: () => updateTab(1, const Activity()),
),
InkWell(
onTap: () {
updateTab(4, const ListActivity());
},
child: Container(
width: 65,
height: 65,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: TColor.primaryG,
),
borderRadius: BorderRadius.circular(35),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
),
],
),
child: Icon(
Icons.search,
color: TColor.white,
size: 35,
onTap: () {
updateTab(4, const ListActivity());
},
child: Container(
width: 65,
height: 65,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: TColor.primaryG,
),
borderRadius: BorderRadius.circular(35),
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
),
],
),
child: Icon(
Icons.search,
color: TColor.white,
size: 35,
),
),
),
sideBarButton(
icon: "assets/img/Camera_tab.svg",
selectIcon: "assets/img/Camera_tab_select.svg",
icon: "assets/img/icon_map.svg",
selectIcon: "assets/img/icon_map.svg",
index: 2,
onTap: () => updateTab(2, const MyMap()),
),
@ -94,19 +94,20 @@ class _WebMainTabViewState extends State<WebMainTabView> {
child: Container(
decoration: BoxDecoration(
color: TColor.white,
boxShadow: [
boxShadow: const [
BoxShadow(
color: Colors.black12,
blurRadius: 2,
offset: const Offset(-2, 0), // Ajout d'une ombre sur le côté
offset: Offset(-2, 0), // Ajout d'une ombre sur le côté
),
],
),
child: Scaffold(
backgroundColor: TColor.white,
body: currentTab,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: SizedBox(
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: const SizedBox(
width: 70,
height: 70,
),

@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/view/map/mobile/mobile_my_map.dart';
import 'package:smartfit_app_mobile/view/map/my_map_osm.dart';
class ChoseMap extends StatefulWidget {
const ChoseMap({Key? key}) : super(key: key);
@override
State<ChoseMap> createState() => _ChoseMap();
}
class _ChoseMap extends State<ChoseMap> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: TColor.white,
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MobileMyMaps()));
},
child: const Text("Use map with google map")),
TextButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => const MyMapOSM()));
},
child: const Text("Use map with Open Street Map")),
const Text(
"Mettre une image la en mode une personne avec des jumelles")
],
)),
);
}
}

@ -20,11 +20,14 @@ class _MobileMyMaps extends State<MobileMyMaps> {
Widget build(BuildContext context) {
_polylines = MapUtil().initPolines(context, 10, TColor.primaryColor1);
_cameraPosition =
CameraPosition(target: _polylines.first.points.first, zoom: 18);
CameraPosition(target: _polylines.first.points.first, zoom: 15);
return Scaffold(
body: _getMap(),
);
appBar: AppBar(
title: const Text("Carte Google Map "),
backgroundColor: TColor.primaryColor1,
),
body: _getMap());
}
Widget _getMap() {

@ -4,8 +4,7 @@ import 'package:responsive_builder/responsive_builder.dart';
import 'package:smartfit_app_mobile/modele/activity.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/view/home/no_activity_view.dart';
import 'package:smartfit_app_mobile/view/map/mobile/mobile_my_map.dart';
import 'package:smartfit_app_mobile/view/map/web/web_my_map.dart';
import 'package:smartfit_app_mobile/view/map/chose_map.dart';
class MyMap extends StatefulWidget {
const MyMap({Key? key}) : super(key: key);
@ -35,8 +34,8 @@ class _MyMapState extends State<MyMap> {
);
}
return ScreenTypeLayout.builder(
mobile: (_) => const MobileMyMaps(),
desktop: (_) => const WebMyMaps(),
mobile: (_) => const ChoseMap(),
desktop: (_) => const ChoseMap(),
);
}
}

@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart' as osm;
import 'package:smartfit_app_mobile/common/colo_extension.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
class MyMapOSM extends StatefulWidget {
const MyMapOSM({Key? key}) : super(key: key);
@override
State<MyMapOSM> createState() => _MyMapOSM();
}
class _MyMapOSM extends State<MyMapOSM> {
final controller = MapController();
@override
Widget build(BuildContext context) {
List<osm.LatLng> listPolynines =
context.watch<User>().managerSelectedActivity.getPositionOSM();
return Scaffold(
appBar: AppBar(
title: const Text("Carte Open Street Map "),
backgroundColor: TColor.primaryColor1,
),
body: FlutterMap(
options: MapOptions(center: listPolynines.first),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
),
PolylineLayer(
polylines: [
Polyline(
points: listPolynines,
color: TColor.primaryColor1,
strokeWidth: 5.0,
),
],
),
],
),
);
}
}

@ -1,117 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
class MyMap extends StatefulWidget {
const MyMap({ Key? key }) : super(key: key);
@override
State<MyMap> createState() => _MyMapState();
}
class _MyMapState extends State<MyMap> {
Completer<GoogleMapController> _googleMapController = Completer();
CameraPosition? _cameraPosition;
Location? _location;
LocationData? _currentLocation;
@override
void initState() {
_init();
super.initState();
}
_init() async {
_location = Location();
_cameraPosition = CameraPosition(
target: LatLng(0, 0), // this is just the example lat and lng for initializing
zoom: 15
);
_initLocation();
}
//function to listen when we move position
_initLocation() {
//use this to go to current location instead
_location?.getLocation().then((location) {
_currentLocation = location;
});
_location?.onLocationChanged.listen((newLocation) {
_currentLocation = newLocation;
moveToPosition(LatLng(_currentLocation?.latitude ?? 0, _currentLocation?.longitude ?? 0));
});
}
moveToPosition(LatLng latLng) async {
GoogleMapController mapController = await _googleMapController.future;
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: latLng,
zoom: 15
)
)
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(),
);
}
Widget _buildBody() {
return _getMap();
}
Widget _getMarker() {
return Container(
width: 40,
height: 40,
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(100),
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0,3),
spreadRadius: 4,
blurRadius: 6
)
]
),
child: ClipOval(child: Image.asset("assets/img/u1.png")),
);
}
Widget _getMap() {
return Stack(
children: [
GoogleMap(
initialCameraPosition: _cameraPosition!,
mapType: MapType.normal,
onMapCreated: (GoogleMapController controller) {
// now we need a variable to get the controller of google map
if (!_googleMapController.isCompleted) {
_googleMapController.complete(controller);
}
},
),
Positioned.fill(
child: Align(
alignment: Alignment.center,
child: _getMarker()
)
)
],
);
}
}

@ -21,11 +21,14 @@ class _WebMyMaps extends State<WebMyMaps> {
Widget build(BuildContext context) {
_polylines = MapUtil().initPolines(context, 10, TColor.primaryColor1);
_cameraPosition =
CameraPosition(target: _polylines.first.points.first, zoom: 18);
CameraPosition(target: _polylines.first.points.first, zoom: 5);
return Scaffold(
body: _getMap(),
);
appBar: AppBar(
title: const Text("Carte Google Map "),
backgroundColor: TColor.primaryColor1,
),
body: _getMap());
}
Widget _getMap() {

@ -1,6 +1,7 @@
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:csv/csv.dart';
import 'package:fit_tool/fit_tool.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
@ -8,6 +9,7 @@ import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart';
import 'dart:io';
import 'package:smartfit_app_mobile/modele/api/i_data_strategy.dart';
import 'package:smartfit_app_mobile/modele/manager_file.dart';
import 'package:smartfit_app_mobile/modele/user.dart';
import 'package:smartfit_app_mobile/modele/api/request_api.dart';
import 'package:tuple/tuple.dart';
@ -82,6 +84,8 @@ class _TestPage extends State<TestPage> {
//late File x = File(file.path);
Future<void> readFile() async {
ManagerFile managerFile = ManagerFile();
PlatformFile t = result!.files.single;
String? y = t.path;
if (t.path == null) {
@ -91,15 +95,13 @@ class _TestPage extends State<TestPage> {
final content = await file.readAsBytes();
FitFile fitFile = FitFile.fromBytes(content);
//print(fitFile.toRows());
print("--------------");
print("--------------");
print("--------------");
//print("${await _managerFile.localPath}\\test.csv");
//final outFile = File("${await _managerFile.localPath}\\test.csv");
//final csv = const ListToCsvConverter().convert(fitFile.toRows());
//await outFile.writeAsString(csv);
final outFile = File("${await managerFile.localPath}\\test.csv");
final csv = const ListToCsvConverter().convert(fitFile.toRows());
await outFile.writeAsString(csv);
/*
// ----------- Lire le fit et extarire les données qu'on choisi ----------- //
List<Record> liste = fitFile.records;
List<String> allowedField = [
@ -180,7 +182,7 @@ class _TestPage extends State<TestPage> {
//print(x.getDistanceWithTime(ActivityOfUser(result)));
//print(x.getDistance(ActivityOfUser(result)));
//print(x.getAltitudeWithTime(ActivityOfUser(result)));
//print(x.getSpeedWithTime(ActivityOfUser(result)));
//print(x.getSpeedWithTime(ActivityOfUser(result)));*/
}
}

@ -60,6 +60,8 @@ dependencies:
objectbox: ^2.3.1
objectbox_flutter_libs: any
path: ^1.8.3
flutter_map: ^5.0.0
latlong2: ^0.9.0
dev_dependencies:
flutter_test:

Loading…
Cancel
Save