theeddiestudio

Untitled

Feb 11th, 2025
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.16 KB | None | 0 0
  1. there is a problem in my code. to reproduce the problem one must follow these steps:
  2. 1) edit data and upload in bf page, you will get the correct body fat.
  3. 2) go to settings page and turn off metric system and come back to bf page.
  4. - now the problem that happens are:
  5. a) the text fields don't get autoconverted to inches/lbs etc.
  6.  
  7. i dont want to upload non metric values to the database for consistency of the data. so that is why i am keeping the values of _neck,.... etc as different from the ones used in calculation. I want to make sure that the data uploaded to the database is always in cm (metric) regardless of how a user uses the measurement system. help me.
  8.  
  9. import 'package:flutter/material.dart';
  10. import 'package:shared_preferences/shared_preferences.dart';
  11. import 'dart:math';
  12. import 'dart:io';
  13. import 'dart:convert';
  14. import 'bfdb_helper.dart'; // Import new helper
  15. import 'fat_entry.dart';
  16.  
  17. class BodyFatTrackerPage extends StatefulWidget {
  18. const BodyFatTrackerPage({super.key});
  19.  
  20. @override
  21. State<BodyFatTrackerPage> createState() => _BodyFatTrackerPageState();
  22. }
  23.  
  24. class _BodyFatTrackerPageState extends State<BodyFatTrackerPage> {
  25. bool _isMetricSystem = true;
  26. double _lengthModifier = 0.393701; // cm to inches
  27. double _weightModifier = 2.20462; // kg to lbs
  28.  
  29. double? _fatMass;
  30. double? _leanMass;
  31.  
  32. final _formKey = GlobalKey<FormState>();
  33. String _gender = 'male';
  34. double? _height;
  35. double? _weight;
  36. double? _neck;
  37. double? _waist;
  38. double? _hip;
  39. double? _bodyFat;
  40. DateTime _currentDate = DateTime.now();
  41. final TextEditingController _heightController = TextEditingController();
  42. final TextEditingController _weightController = TextEditingController();
  43. final TextEditingController _neckController = TextEditingController();
  44. final TextEditingController _waistController = TextEditingController();
  45. final TextEditingController _hipController = TextEditingController();
  46.  
  47. @override
  48. void initState() {
  49. super.initState();
  50. _initializePage();
  51. }
  52.  
  53. Future<void> _initializePage() async {
  54. final path = await _getSettingsPath();
  55. final settingsFile = File(path);
  56.  
  57. if (await settingsFile.exists()) {
  58. final jsonString = await settingsFile.readAsString();
  59. final settings = jsonDecode(jsonString);
  60. setState(() {
  61. _isMetricSystem = settings['measurement_system'] ?? true;
  62. _lengthModifier =
  63. _isMetricSystem ? 0.393701 : 1.0; // Set modifier based on system
  64. _weightModifier = _isMetricSystem ? 2.20462 : 1.0;
  65. });
  66. }
  67. await _loadSavedData();
  68. }
  69.  
  70. Future<String> _getSettingsPath() async {
  71. final dir = Directory('/storage/emulated/0/.wtracker/settings');
  72. if (!await dir.exists()) {
  73. await dir.create(recursive: true);
  74. }
  75. return '${dir.path}/settings.json';
  76. }
  77.  
  78. Future<void> _loadSavedData() async {
  79. final fatDbHelper = FatEntryDatabaseHelper.instance;
  80.  
  81. final entry = await fatDbHelper
  82. .getFatEntry(_currentDate.toLocal().toString().split(' ')[0]);
  83.  
  84. final prefs = await SharedPreferences.getInstance();
  85. double? sharedPrefHeight = prefs.getDouble('height');
  86. double? sharedPrefWeight = prefs.getDouble('weight');
  87. String? sharedPrefGender = prefs.getString('gender');
  88.  
  89. setState(() {
  90. _gender = sharedPrefGender ??
  91. 'male'; // Default to 'male' if sharedPrefGender is null
  92. _height = sharedPrefHeight; // Only height from shared preferences
  93. _weight = sharedPrefWeight; // Weight from sharedPrefWeight if available
  94.  
  95. _heightController.text = _height != null
  96. ? (_isMetricSystem
  97. ? _height!.toStringAsFixed(2)
  98. : (_height! * _lengthModifier).toStringAsFixed(2))
  99. : '';
  100.  
  101. _weightController.text = _weight != null
  102. ? (_isMetricSystem
  103. ? _weight!.toStringAsFixed(2)
  104. : (_weight! * _weightModifier).toStringAsFixed(2))
  105. : '';
  106.  
  107. if (entry != null) {
  108. _neck = entry.neck;
  109. _waist = entry.waist;
  110. _hip = entry.hip;
  111. _bodyFat = entry.bodyFat;
  112. _fatMass = entry.fatMass;
  113. _leanMass = entry.leanMass;
  114.  
  115. _neckController.text = _neck != null
  116. ? (_isMetricSystem
  117. ? _neck!.toStringAsFixed(0)
  118. : (_neck! * _lengthModifier).toStringAsFixed(0))
  119. : '';
  120.  
  121. _waistController.text = _waist != null
  122. ? (_isMetricSystem
  123. ? _waist!.toStringAsFixed(0)
  124. : (_waist! * _lengthModifier).toStringAsFixed(0))
  125. : '';
  126.  
  127. _hipController.text = _hip != null
  128. ? (_isMetricSystem
  129. ? _hip!.toStringAsFixed(0)
  130. : (_hip! * _lengthModifier).toStringAsFixed(0))
  131. : '';
  132.  
  133. _heightController.text = _height?.toString() ?? '';
  134. _weightController.text =
  135. _weight?.toString() ?? sharedPrefWeight?.toString() ?? '';
  136. } else {
  137. _heightController.text = _height?.toString() ?? '';
  138. _weightController.text = _weight?.toString() ?? '';
  139. _neckController.clear();
  140. _waistController.clear();
  141. _hipController.clear();
  142. _bodyFat = null;
  143. _fatMass = null;
  144. _leanMass = null;
  145. }
  146. });
  147. }
  148.  
  149. void _calculateFatAndLeanMass() {
  150. if (_bodyFat != null && _weight != null) {
  151. _fatMass = (_bodyFat! * _weight!) / 100;
  152. _leanMass = (_weight! - _fatMass!);
  153. } else {
  154. _fatMass = null;
  155. _leanMass = null;
  156. }
  157. }
  158.  
  159. Future<void> _saveHeight(double height) async {
  160. final prefs = await SharedPreferences.getInstance();
  161. await prefs.setDouble('height', height);
  162. setState(() {
  163. _height = height;
  164. });
  165. }
  166.  
  167. Future<void> _saveGender(String gender) async {
  168. final prefs = await SharedPreferences.getInstance();
  169. await prefs.setString('gender', gender);
  170. setState(() {
  171. _gender = gender;
  172. });
  173. }
  174.  
  175. Future<void> _saveWeight(double weight) async {
  176. final prefs = await SharedPreferences.getInstance();
  177. await prefs.setDouble('weight', weight);
  178. setState(() {
  179. _weight = weight;
  180. });
  181. }
  182.  
  183. // ... (US Navy calculation methods remain the same)
  184.  
  185. Future<void> _saveFatEntry() async {
  186. if (_formKey.currentState!.validate()) {
  187. _formKey.currentState!.save();
  188. _bodyFat = _calculateBodyFat();
  189. _calculateFatAndLeanMass();
  190.  
  191. // Convert to metric if necessary
  192. double leanMassInMetric =
  193. _isMetricSystem ? _leanMass! : _leanMass! / _weightModifier;
  194. double fatMassInMetric =
  195. _isMetricSystem ? _fatMass! : _fatMass! / _weightModifier;
  196. double neckInMetric = _isMetricSystem ? _neck! : _neck! / _lengthModifier;
  197. double waistInMetric =
  198. _isMetricSystem ? _waist! : _waist! / _lengthModifier;
  199. double? hipInMetric = _hip == null
  200. ? null
  201. : (_isMetricSystem ? _hip! : _hip! / _lengthModifier);
  202.  
  203. final fatDbHelper = FatEntryDatabaseHelper.instance;
  204. final entry = FatEntry(
  205. date: _currentDate.toLocal().toString().split(' ')[0],
  206. neck: neckInMetric,
  207. waist: waistInMetric,
  208. hip: hipInMetric,
  209. bodyFat: _bodyFat,
  210. fatMass: fatMassInMetric,
  211. leanMass: leanMassInMetric,
  212. );
  213.  
  214. await fatDbHelper.insertFatEntry(entry);
  215. ScaffoldMessenger.of(context).showSnackBar(
  216. const SnackBar(content: Text('Body fat data saved!')),
  217. );
  218. }
  219. }
  220.  
  221. double? _calculateBodyFat() {
  222. if (_height == null || _weight == null || _neck == null || _waist == null) {
  223. return null; // Not enough data
  224. }
  225.  
  226. // Define log10 function
  227. double log10(double x) => log(x) / log(10);
  228.  
  229. double heightInInches =
  230. _isMetricSystem ? _height! * _lengthModifier : _height!;
  231. double neckInInches = _isMetricSystem ? _neck! * _lengthModifier : _neck!;
  232. double waistInInches =
  233. _isMetricSystem ? _waist! * _lengthModifier : _waist!;
  234.  
  235. if (_gender == 'male') {
  236. _bodyFat = (86.010 * log10(waistInInches - neckInInches)) -
  237. (70.041 * log10(heightInInches)) +
  238. 36.76;
  239. } else {
  240. if (_hip == null) return null; // Hip measurement required for women
  241. double hipInInches = _isMetricSystem ? _hip! * _lengthModifier : _hip!;
  242.  
  243. _bodyFat = (163.205 * log10(waistInInches + hipInInches - neckInInches)) -
  244. (97.684 * log(heightInInches)) -
  245. 78.387;
  246. }
  247.  
  248. return _bodyFat;
  249. }
  250.  
  251. Color _getBodyFatColor(double bodyFat) {
  252. if (bodyFat > 20) {
  253. return Colors.red; // Red for body fat over 20%
  254. } else if (bodyFat > 15) {
  255. return Colors.yellow; // Yellow for body fat between 15% and 20%
  256. } else {
  257. return Colors.green; // Green for body fat under 15%
  258. }
  259. }
  260.  
  261. // Update the input fields' labels based on the measurement system
  262. String _getHeightLabel() =>
  263. _isMetricSystem ? 'Height (cm)' : 'Height (inches)';
  264. String _getWeightLabel() => _isMetricSystem ? 'Weight (kg)' : 'Weight (lbs)';
  265. String _getNeckLabel() => _isMetricSystem ? 'Neck (cm)' : 'Neck (inches)';
  266. String _getWaistLabel() => _isMetricSystem ? 'Waist (cm)' : 'Waist (inches)';
  267. String _getHipLabel() => _isMetricSystem ? 'Hip (cm)' : 'Hip (inches)';
  268.  
  269. @override
  270. Widget build(BuildContext context) {
  271. return Scaffold(
  272. body: Padding(
  273. padding: const EdgeInsets.all(6.0),
  274. child: Form(
  275. key: _formKey,
  276. child: Column(
  277. children: [
  278. const SizedBox(height: 25),
  279. Row(
  280. children: [
  281. Radio<String>(
  282. value: 'male',
  283. groupValue: _gender,
  284. onChanged: (value) {
  285. setState(() {
  286. _saveGender(value!); // Use null assertion operator
  287. });
  288. },
  289. ),
  290. const Text('Male'),
  291. const SizedBox(width: 20),
  292. Radio<String>(
  293. value: 'female',
  294. groupValue: _gender,
  295. onChanged: (value) {
  296. setState(() {
  297. _saveGender(value!); // Use null assertion operator
  298. });
  299. },
  300. ),
  301. const Text('Female'),
  302. ],
  303. ),
  304. const SizedBox(height: 5),
  305. const Divider(thickness: 3),
  306. const SizedBox(height: 5),
  307. // Height input
  308. TextFormField(
  309. controller: _heightController,
  310. decoration: InputDecoration(labelText: _getHeightLabel()),
  311. keyboardType: TextInputType.number,
  312. validator: (value) {
  313. if (value == null || value.isEmpty) {
  314. return 'Please enter height';
  315. }
  316. return null;
  317. },
  318. onSaved: (value) {
  319. _height = double.tryParse(value!);
  320. if (_height != null) {
  321. _saveHeight(_height!);
  322. }
  323. },
  324. ),
  325.  
  326. // Weight input
  327. TextFormField(
  328. controller: _weightController,
  329. decoration: InputDecoration(labelText: _getWeightLabel()),
  330. keyboardType: TextInputType.number,
  331. validator: (value) {
  332. if (value == null || value.isEmpty) {
  333. return 'Please enter weight';
  334. }
  335. return null;
  336. },
  337. onSaved: (value) {
  338. _weight = double.tryParse(value!);
  339. if (_weight != null) {
  340. _saveWeight(_weight!);
  341. }
  342. },
  343. ),
  344.  
  345. // Neck circumference input
  346. TextFormField(
  347. controller: _neckController,
  348. decoration: InputDecoration(labelText: _getNeckLabel()),
  349. keyboardType: TextInputType.number,
  350. validator: (value) {
  351. if (value == null || value.isEmpty) {
  352. return 'Please enter neck circumference';
  353. }
  354. return null;
  355. },
  356. onSaved: (value) {
  357. _neck = double.tryParse(value!);
  358. },
  359. ),
  360.  
  361. // Waist circumference input
  362. TextFormField(
  363. controller: _waistController,
  364. decoration: InputDecoration(labelText: _getWaistLabel()),
  365. keyboardType: TextInputType.number,
  366. validator: (value) {
  367. if (value == null || value.isEmpty) {
  368. return 'Please enter waist circumference';
  369. }
  370. return null;
  371. },
  372. onSaved: (value) {
  373. _waist = double.tryParse(value!);
  374. },
  375. ),
  376.  
  377. // Hip circumference input - only for women
  378. if (_gender == 'female')
  379. TextFormField(
  380. controller: _hipController,
  381. decoration: InputDecoration(labelText: _getHipLabel()),
  382. keyboardType: TextInputType.number,
  383. validator: (value) {
  384. if (value == null || value.isEmpty) {
  385. return 'Please enter hip circumference';
  386. }
  387. return null;
  388. },
  389. onSaved: (value) {
  390. _hip = double.tryParse(value!);
  391. },
  392. ),
  393. const SizedBox(height: 10),
  394.  
  395. if (_fatMass != null && _leanMass != null)
  396. Column(
  397. children: [
  398. Text(
  399. 'Body Fat Mass: ${_isMetricSystem ? _fatMass!.toStringAsFixed(2) + ' kg' : (_fatMass! * _weightModifier).toStringAsFixed(2) + ' lbs'}',
  400. style: const TextStyle(fontSize: 16),
  401. ),
  402. Text(
  403. 'Lean Body Mass: ${_isMetricSystem ? _leanMass!.toStringAsFixed(2) + ' kg' : (_leanMass! * _weightModifier).toStringAsFixed(2) + ' lbs'}',
  404. style: const TextStyle(fontSize: 16),
  405. ),
  406. Text(
  407. 'Debug: Height: ${_height?.toStringAsFixed(2) ?? 'N/A'}, '
  408. 'Weight: ${_weight?.toStringAsFixed(2) ?? 'N/A'}, '
  409. 'Neck: ${_neck?.toStringAsFixed(2) ?? 'N/A'}, '
  410. 'Waist: ${_waist?.toStringAsFixed(2) ?? 'N/A'}, '
  411. 'Hip: ${_hip?.toStringAsFixed(2) ?? 'N/A'}',
  412. style: const TextStyle(fontSize: 13),
  413. ),
  414. ],
  415. ),
  416.  
  417. const SizedBox(height: 12),
  418.  
  419. // Display calculated body fat
  420. _calculateBodyFat() != null
  421. ? Text(
  422. 'Body Fat: ${_calculateBodyFat()?.toStringAsFixed(2)}%',
  423. style: TextStyle(
  424. fontSize: 20,
  425. fontWeight: FontWeight.bold,
  426. color: _getBodyFatColor(
  427. _calculateBodyFat()!), // Apply color based on body fat value
  428. ),
  429. )
  430. : (_height != null
  431. ? const Text(
  432. 'Body Fat: 0.0',
  433. style: TextStyle(
  434. fontSize: 20,
  435. fontWeight: FontWeight.bold,
  436. ),
  437. )
  438. : Container()),
  439. const SizedBox(height: 4),
  440. const Divider(thickness: 2),
  441. const SizedBox(height: 4),
  442. ElevatedButton(
  443. onPressed: _saveFatEntry,
  444. child: const Text('Upload'),
  445. ),
  446. ],
  447. ),
  448. ),
  449. ),
  450. );
  451. }
  452. }
Advertisement
Add Comment
Please, Sign In to add comment