From de5815c71cbc7a582750bcf6592174a4b619491f Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Wed, 22 Feb 2023 01:28:01 +0100 Subject: [PATCH 1/7] wip --- lib/interface/db_record.dart | 2 ++ lib/main.dart | 7 +++-- lib/models/hiit_workout.dart | 26 +++++++++++++--- lib/models/mood.dart | 9 ++++++ lib/models/sleep.dart | 11 +++++++ lib/service/database_service.dart | 51 +++++++++++++++++++++++++++++++ lib/widgets/mood_form.dart | 8 +++-- pubspec.lock | 27 ++++++++++++++-- pubspec.yaml | 7 +++-- 9 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 lib/service/database_service.dart diff --git a/lib/interface/db_record.dart b/lib/interface/db_record.dart index f5c56c8..df9c329 100644 --- a/lib/interface/db_record.dart +++ b/lib/interface/db_record.dart @@ -1,3 +1,5 @@ abstract class DatabaseRecord { String toCSV(); + Map toMap(); + DatabaseRecord.fromMap(Map map); } diff --git a/lib/main.dart b/lib/main.dart index 6e5d7a5..bb80057 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/pages/main_page.dart'; -void main() => runApp(const MyApp()); +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + runApp(const MyApp()); +} class MyApp extends StatelessWidget { const MyApp({super.key}); @@ -10,6 +13,6 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp(title: _title, home: MyHomePage()); + return const MaterialApp(title: _title, home: MyHomePage()); } } diff --git a/lib/models/hiit_workout.dart b/lib/models/hiit_workout.dart index 9aa69eb..48e599c 100644 --- a/lib/models/hiit_workout.dart +++ b/lib/models/hiit_workout.dart @@ -1,15 +1,33 @@ import 'package:smoke_cess_app/interface/db_record.dart'; class HIITWorkout implements DatabaseRecord { - final Duration _workoutDuration; - final String _commentBefore; - final String _commentAfter; - final DateTime _workoutDate; + Duration _workoutDuration; + String _commentBefore; + String _commentAfter; + DateTime _workoutDate; HIITWorkout(this._workoutDuration, this._commentBefore, this._commentAfter, this._workoutDate); + /* @override + HIITWorkout.fromMap(Map map) { + _workoutDuration = map['_workoutDuration']; + _commentBefore = map['_commentBefore']; + _commentAfter = map['_commentAfter']; + _workoutDate = map['_workoutDate']; + } */ + @override String toCSV() => "${_workoutDate.toIso8601String()}, $_workoutDuration, $_commentBefore, $_commentAfter"; + + @override + Map toMap() { + return { + 'workoutDuration': _workoutDuration, + 'commentBefore': _commentBefore, + 'commentAfter': _commentAfter, + 'workoutDate': _workoutDate, + }; + } } diff --git a/lib/models/mood.dart b/lib/models/mood.dart index d17061a..4914791 100644 --- a/lib/models/mood.dart +++ b/lib/models/mood.dart @@ -11,4 +11,13 @@ class Mood implements DatabaseRecord { String toCSV() { return "${_date.toIso8601String()}, ${_moodValue.round().toString()}, $_comment"; } + + @override + Map toMap() { + return { + 'moodValue': _moodValue, + 'comment': _comment, + 'date': _date, + }; + } } diff --git a/lib/models/sleep.dart b/lib/models/sleep.dart index f94be2e..05459fd 100644 --- a/lib/models/sleep.dart +++ b/lib/models/sleep.dart @@ -15,4 +15,15 @@ class Sleep implements DatabaseRecord { String toCSV() { return "${_date.toIso8601String()}, ${_sleepQualityValue.round().toString()}, $_sleepedAt, $_wokeUpAt, $_comment"; } + + @override + Map toMap() { + return { + 'sleepQualityValue': _sleepQualityValue, + 'comment': _comment, + 'date': _date, + 'sleepedAt': _sleepedAt, + 'wokeUpAt': _wokeUpAt, + }; + } } diff --git a/lib/service/database_service.dart b/lib/service/database_service.dart new file mode 100644 index 0000000..9fe8dba --- /dev/null +++ b/lib/service/database_service.dart @@ -0,0 +1,51 @@ +import 'dart:async'; + +import 'package:path/path.dart'; +import 'package:smoke_cess_app/models/mood.dart'; +import 'package:sqflite/sqflite.dart'; +// ignore: depend_on_referenced_packages +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; + +class DatabaseService { + DatabaseService._privateConstructor(); + static final DatabaseService instance = DatabaseService._privateConstructor(); + + static Database? _database; + Future get database async => _database ??= await _initDatabase(); + + Future _initDatabase() async { + Directory documentsDirectory = await getApplicationDocumentsDirectory(); + String path = join(documentsDirectory.path, 'database.db'); + return await openDatabase( + path, + version: 1, + onCreate: _onCreate, + ); + } + + Future _onCreate(Database db, int version) async { + await db.execute(''' + CREATE TABLE mood( + id INTEGER PRIMARY KEY, + value INTEGER, + date TEXT, + comment TEXT + ) + '''); + } + + Future> getMoodRecords() async { + Database db = await instance.database; + var moodRecords = await db.query('mood'); + List moodList = moodRecords.isNotEmpty + ? moodRecords.map((e) => Mood(1, 'comment', DateTime.now())).toList() + : []; + return moodList; + } + + Future addMood(Mood mood) async { + Database db = await instance.database; + return await db.insert('mood', mood.toMap()); + } +} diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index a5c059f..ca9858e 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; import 'package:smoke_cess_app/widgets/slider.dart'; import 'package:smoke_cess_app/widgets/submit_form_button.dart'; import 'package:smoke_cess_app/widgets/text_formfield.dart'; @@ -20,9 +22,9 @@ class _MoodFormState extends State { void submitForm() { if (_moodFormKey.currentState!.validate()) { _moodFormKey.currentState?.save(); //call every onSave Method - //TODO Businesslogik aufrufen! - print(_textInput); - print(slider.getSliderValue()); + Mood mood = Mood(slider.getSliderValue(), _textInput, DateTime.now()); + print(mood.toCSV()); + DatabaseService.instance.addMood(mood); _moodFormKey.currentState?.reset(); } } diff --git a/pubspec.lock b/pubspec.lock index e039943..e044c9f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -199,14 +199,14 @@ packages: source: hosted version: "3.0.0" path: - dependency: transitive + dependency: "direct main" description: name: path url: "https://pub.dartlang.org" source: hosted version: "1.8.2" path_provider: - dependency: transitive + dependency: "direct main" description: name: path_provider url: "https://pub.dartlang.org" @@ -329,6 +329,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.4+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.2+2" stack_trace: dependency: transitive description: @@ -350,6 +364,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" term_glyph: dependency: transitive description: @@ -401,4 +422,4 @@ packages: version: "1.0.0" sdks: dart: ">=2.18.2 <3.0.0" - flutter: ">=3.0.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index 58445b3..f30d59d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -20,7 +20,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.18.2 <3.0.0" + sdk: '>=2.18.2 <3.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -31,6 +31,9 @@ environment: dependencies: flutter: sdk: flutter + sqflite: + path: + path_provider: ^2.0.12 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From 9a13cfb9f1ff713631f3d3520b9854ab9f748fba Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 15:30:04 +0100 Subject: [PATCH 2/7] date to string --- lib/models/mood.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/models/mood.dart b/lib/models/mood.dart index 4914791..5d71e5b 100644 --- a/lib/models/mood.dart +++ b/lib/models/mood.dart @@ -15,9 +15,9 @@ class Mood implements DatabaseRecord { @override Map toMap() { return { - 'moodValue': _moodValue, + 'value': _moodValue, 'comment': _comment, - 'date': _date, + 'date': _date.toIso8601String(), }; } } From abbbc4a8c49b712a5155455895dd8afaaf4716de Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 18:54:23 +0100 Subject: [PATCH 3/7] changed models, added function from db to model --- lib/interface/db_record.dart | 2 +- lib/models/hiit_workout.dart | 13 ++++++------- lib/models/mood.dart | 10 ++++++++-- lib/models/sleep.dart | 24 ++++++++++++++++++------ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/lib/interface/db_record.dart b/lib/interface/db_record.dart index df9c329..ed213ec 100644 --- a/lib/interface/db_record.dart +++ b/lib/interface/db_record.dart @@ -1,5 +1,5 @@ abstract class DatabaseRecord { String toCSV(); Map toMap(); - DatabaseRecord.fromMap(Map map); + DatabaseRecord.fromDatabase(Map map); } diff --git a/lib/models/hiit_workout.dart b/lib/models/hiit_workout.dart index 48e599c..c4ec0da 100644 --- a/lib/models/hiit_workout.dart +++ b/lib/models/hiit_workout.dart @@ -9,13 +9,12 @@ class HIITWorkout implements DatabaseRecord { HIITWorkout(this._workoutDuration, this._commentBefore, this._commentAfter, this._workoutDate); - /* @override - HIITWorkout.fromMap(Map map) { - _workoutDuration = map['_workoutDuration']; - _commentBefore = map['_commentBefore']; - _commentAfter = map['_commentAfter']; - _workoutDate = map['_workoutDate']; - } */ + //TODO Felder anpassen + @override + factory HIITWorkout.fromMap(Map map) { + return HIITWorkout(map['_workoutDuration'], map['_commentBefore'], + map['_commentAfter'], map['_workoutDate']); + } @override String toCSV() => diff --git a/lib/models/mood.dart b/lib/models/mood.dart index 5d71e5b..562b2b4 100644 --- a/lib/models/mood.dart +++ b/lib/models/mood.dart @@ -1,15 +1,21 @@ import 'package:smoke_cess_app/interface/db_record.dart'; class Mood implements DatabaseRecord { - final double _moodValue; + final int _moodValue; final String _comment; final DateTime _date; Mood(this._moodValue, this._comment, this._date); + @override + factory Mood.fromDatabase(Map map) { + DateTime date = DateTime.parse(map['date']); + return Mood(map['value'], map['comment'], date); + } + @override String toCSV() { - return "${_date.toIso8601String()}, ${_moodValue.round().toString()}, $_comment"; + return "${_date.toIso8601String()}, $_moodValue, $_comment"; } @override diff --git a/lib/models/sleep.dart b/lib/models/sleep.dart index 05459fd..d5335a8 100644 --- a/lib/models/sleep.dart +++ b/lib/models/sleep.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/interface/db_record.dart'; class Sleep implements DatabaseRecord { - final double _sleepQualityValue; + final int _sleepQualityValue; final String _comment; final DateTime _date; final TimeOfDay _sleepedAt; @@ -11,19 +11,31 @@ class Sleep implements DatabaseRecord { Sleep(this._sleepQualityValue, this._comment, this._date, this._sleepedAt, this._wokeUpAt); + @override + factory Sleep.fromDatabase(Map map) { + DateTime date = DateTime.parse(map['date']); + TimeOfDay sleepedAt = + TimeOfDay(hour: map['sleepedAtHour'], minute: map['sleepedAtMinute']); + TimeOfDay wokeUpAt = + TimeOfDay(hour: map['wokeUpAtHour'], minute: map['wokeUpAtMinute']); + return Sleep(map['value'], map['comment'], date, sleepedAt, wokeUpAt); + } + @override String toCSV() { - return "${_date.toIso8601String()}, ${_sleepQualityValue.round().toString()}, $_sleepedAt, $_wokeUpAt, $_comment"; + return "${_date.toIso8601String()}, $_sleepQualityValue, ${_sleepedAt.hour}:${_sleepedAt.minute}, ${_wokeUpAt.hour}:${_wokeUpAt.minute}, $_comment"; } @override Map toMap() { return { - 'sleepQualityValue': _sleepQualityValue, + 'value': _sleepQualityValue, 'comment': _comment, - 'date': _date, - 'sleepedAt': _sleepedAt, - 'wokeUpAt': _wokeUpAt, + 'date': _date.toIso8601String(), + 'sleepedAtHour': _sleepedAt.hour, + 'sleepedAtMinute': _sleepedAt.minute, + 'wokeUpAtHour': _wokeUpAt.hour, + 'wokeUpAtMinute': _wokeUpAt.minute, }; } } From 265e17488921dd9871b6e7d4966d3b50cb4a6ac1 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 18:54:54 +0100 Subject: [PATCH 4/7] use int for slider value in form, save model on form complete --- lib/widgets/mood_form.dart | 4 ++-- lib/widgets/sleep_form.dart | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index ca9858e..205e4d6 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -22,8 +22,8 @@ class _MoodFormState extends State { void submitForm() { if (_moodFormKey.currentState!.validate()) { _moodFormKey.currentState?.save(); //call every onSave Method - Mood mood = Mood(slider.getSliderValue(), _textInput, DateTime.now()); - print(mood.toCSV()); + Mood mood = + Mood(slider.getSliderValue().toInt(), _textInput, DateTime.now()); DatabaseService.instance.addMood(mood); _moodFormKey.currentState?.reset(); } diff --git a/lib/widgets/sleep_form.dart b/lib/widgets/sleep_form.dart index 52eefe8..5564c7d 100644 --- a/lib/widgets/sleep_form.dart +++ b/lib/widgets/sleep_form.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/models/sleep.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; import 'package:smoke_cess_app/widgets/elevated_card.dart'; import 'package:smoke_cess_app/widgets/slider.dart'; import 'package:smoke_cess_app/widgets/submit_form_button.dart'; @@ -26,10 +28,13 @@ class _SleepFormState extends State { void submitForm() { if (_sleepFormKey.currentState!.validate()) { _sleepFormKey.currentState?.save(); //call every onSave Method - //TODO Businesslogik aufrufen! - print(_textInput); - print(slider.getSliderValue()); - print('Eingeschlafen um: ${sleepTimePicker.getCurrentTime}'); + Sleep sleep = Sleep( + slider.getSliderValue().toInt(), + _textInput, + DateTime.now(), + sleepTimePicker.getCurrentTime, + wakeUpTimePicker.getCurrentTime); + DatabaseService.instance.addSleep(sleep); _sleepFormKey.currentState?.reset(); } } From c6075848cf8fc2882a271db7771678357dbab1f9 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 18:55:03 +0100 Subject: [PATCH 5/7] init database on appstart --- lib/main.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index bb80057..0b6b338 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/pages/main_page.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + //init database + DatabaseService.instance; runApp(const MyApp()); } From be600f98c8ee20719e6b61fade20e6ff183e0a71 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 18:55:49 +0100 Subject: [PATCH 6/7] add missing tables, functionality for sleep save and read --- lib/service/database_service.dart | 85 ++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/lib/service/database_service.dart b/lib/service/database_service.dart index 9fe8dba..26973f4 100644 --- a/lib/service/database_service.dart +++ b/lib/service/database_service.dart @@ -7,6 +7,8 @@ import 'package:sqflite/sqflite.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; +import '../models/sleep.dart'; + class DatabaseService { DatabaseService._privateConstructor(); static final DatabaseService instance = DatabaseService._privateConstructor(); @@ -17,35 +19,90 @@ class DatabaseService { Future _initDatabase() async { Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, 'database.db'); - return await openDatabase( - path, - version: 1, - onCreate: _onCreate, - ); + return await openDatabase(path, + version: 1, onCreate: _onCreate, onOpen: _createTablesIfNotExists); } Future _onCreate(Database db, int version) async { - await db.execute(''' - CREATE TABLE mood( - id INTEGER PRIMARY KEY, - value INTEGER, - date TEXT, - comment TEXT - ) - '''); + await _createTablesIfNotExists(db); } + Future _createTablesIfNotExists(Database db) async { + await db.execute(_createMoodTable); + await db.execute(_createSleepTable); + await db.execute(_createRelapseTable); + await db.execute(_createWorkoutTable); + } + + //TODO use generic function? Future> getMoodRecords() async { Database db = await instance.database; var moodRecords = await db.query('mood'); List moodList = moodRecords.isNotEmpty - ? moodRecords.map((e) => Mood(1, 'comment', DateTime.now())).toList() + ? moodRecords.map((e) => Mood.fromDatabase(e)).toList() : []; return moodList; } + Future> getSleepRecords() async { + Database db = await instance.database; + var sleepRecords = await db.query('sleep'); + List sleepList = sleepRecords.isNotEmpty + ? sleepRecords.map((e) => Sleep.fromDatabase(e)).toList() + : []; + return sleepList; + } + Future addMood(Mood mood) async { Database db = await instance.database; return await db.insert('mood', mood.toMap()); } + + Future addSleep(Sleep sleep) async { + Database db = await instance.database; + return await db.insert('sleep', sleep.toMap()); + } } + +String _createMoodTable = ''' + CREATE TABLE IF NOT EXISTS mood( + id INTEGER PRIMARY KEY, + value INTEGER, + date TEXT, + comment TEXT + ) + '''; + +String _createSleepTable = ''' + CREATE TABLE IF NOT EXISTS sleep( + id INTEGER PRIMARY KEY, + value INTEGER, + date TEXT, + comment TEXT, + sleepedAtHour INTEGER, + sleepedAtMinute INTEGER, + wokeUpAtHour INTEGER, + wokeUpAtMinute INTEGER + ) + '''; + +String _createRelapseTable = ''' + CREATE TABLE IF NOT EXISTS relapse( + id INTEGER PRIMARY KEY, + date TEXT, + comment TEXT, + reason TEXT + ) + '''; + +String _createWorkoutTable = ''' + CREATE TABLE IF NOT EXISTS workout( + id INTEGER PRIMARY KEY, + date TEXT, + motivationBefore INTEGER, + commentBefore TEXT, + motivationAfter INTEGER, + commentAfter TEXT, + completed INTEGER + ) + '''; From e049aceb8f85881836a1830813032e1152d82371 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sat, 25 Feb 2023 18:56:07 +0100 Subject: [PATCH 7/7] added export button for testing read operation on db --- lib/pages/scanner_page.dart | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index fcd2c30..1513ab3 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:smoke_cess_app/models/mood.dart'; import 'package:smoke_cess_app/models/settings.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; import 'package:smoke_cess_app/service/json_service.dart'; import 'package:smoke_cess_app/service/settings_service.dart'; +import '../models/sleep.dart'; import '../widgets/missing_config_popup.dart'; class ScannerPage extends StatefulWidget { @@ -69,6 +72,23 @@ class ScannerPageState extends State { loadSettingsFromLocalJSON(); }, child: const Text('Read JSON'), + ), + const SizedBox(height: 30), + ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20)), + onPressed: () async { + List moods = await DatabaseService.instance.getMoodRecords(); + List sleeps = + await DatabaseService.instance.getSleepRecords(); + for (Mood mood in moods) { + print(mood.toCSV()); + } + for (Sleep sleep in sleeps) { + print(sleep.toCSV()); + } + }, + child: const Text('Export'), ) ], ));