Commit 0d6a734
Changed files (3)
test
lib/model/blood_pressure.dart
@@ -74,25 +74,6 @@ class BloodPressureModel extends ChangeNotifier {
notifyListeners();
}
- /// Returns the last x BloodPressureRecords from new to old.
- /// Caches new ones if necessary
- Future<UnmodifiableListView<BloodPressureRecord>> getLastX(int count) async {
- List<BloodPressureRecord> lastMeasurements = [];
-
- var dbEntries = await _database.query('bloodPressureModel',
- orderBy: 'timestamp DESC', limit: count); // de
- for (var e in dbEntries) {
- lastMeasurements.add(BloodPressureRecord(
- DateTime.fromMillisecondsSinceEpoch(e['timestamp']as int),
- e['systolic'] as int,
- e['diastolic'] as int,
- e['pulse'] as int,
- e['notes'].toString()));
-
- }
- return UnmodifiableListView(lastMeasurements);
- }
-
/// Returns all recordings in saved in a range in ascending order
Future<UnmodifiableListView<BloodPressureRecord>> getInTimeRange(DateTime from, DateTime to) async {
var dbEntries = await _database.query('bloodPressureModel',
@@ -122,52 +103,25 @@ class BloodPressureModel extends ChangeNotifier {
Future<int> get count async {
return (await _database.rawQuery('SELECT COUNT(*) FROM bloodPressureModel'))[0]['COUNT(*)'] as int? ?? -1;
}
- Future<int> get measurementsPerDay async {
- final c = await count;
- if (c <= 1) {
- return -1;
- }
- var firstDay = DateTime.fromMillisecondsSinceEpoch((await _database.rawQuery('SELECT timestamp FROM bloodPressureModel ORDER BY timestamp ASC LIMIT 1'))[0]['timestamp'] as int? ?? -1);
- var lastDay = DateTime.fromMillisecondsSinceEpoch((await _database.rawQuery('SELECT timestamp FROM bloodPressureModel ORDER BY timestamp DESC LIMIT 1'))[0]['timestamp'] as int? ?? -1);
-
- if (lastDay.difference(firstDay).inDays <= 0) {
- return c;
- }
-
- return c ~/ lastDay.difference(firstDay).inDays;
+ Future<DateTime> get firstDay async {
+ return DateTime.fromMillisecondsSinceEpoch((await _database.rawQuery('SELECT timestamp FROM bloodPressureModel ORDER BY timestamp ASC LIMIT 1'))[0]['timestamp'] as int? ?? -1);
+ }
+ Future<DateTime> get lastDay async {
+ return DateTime.fromMillisecondsSinceEpoch((await _database.rawQuery('SELECT timestamp FROM bloodPressureModel ORDER BY timestamp DESC LIMIT 1'))[0]['timestamp'] as int? ?? -1);
}
-
Future<int> get avgDia async {
- var res = (await _database.rawQuery('SELECT AVG(diastolic) as dia FROM bloodPressureModel'))[0]['dia'];
- int? val;
- try {
- val = (res as int?);
- } catch (e) {
- val = (res as double?)?.toInt();
- }
- return val ?? -1;
+ var res = _toInt((await _database.rawQuery('SELECT AVG(diastolic) as dia FROM bloodPressureModel'))[0]['dia']);
+ return res ?? -1;
}
Future<int> get avgSys async {
- var res = (await _database.rawQuery('SELECT AVG(systolic) as sys FROM bloodPressureModel'))[0]['sys'];
- int? val;
- try {
- val = (res as int?);
- } catch (e) {
- val = (res as double?)?.toInt();
- }
- return val ?? -1;
+ var res = _toInt((await _database.rawQuery('SELECT AVG(systolic) as sys FROM bloodPressureModel'))[0]['sys']);
+ return res ?? -1;
}
Future<int> get avgPul async {
- var res = (await _database.rawQuery('SELECT AVG(pulse) as pul FROM bloodPressureModel'))[0]['pul'];
- int? val;
- try {
- val = (res as int?);
- } catch (e) {
- val = (res as double?)?.toInt();
- }
- return val ?? -1;
+ var res = _toInt((await _database.rawQuery('SELECT AVG(pulse) as pul FROM bloodPressureModel'))[0]['pul']);
+ return res ?? -1;
}
Future<int> get maxDia async {
@@ -196,44 +150,6 @@ class BloodPressureModel extends ChangeNotifier {
return (res as int?) ?? -1;
}
- /// outer list is type (0 -> diastolic, 1 -> systolic, 2 -> pulse)
- /// inner list index is hour of day ([0] -> 00:00-00:59; [1] -> ...)
- Future<List<List<int>>> get allAvgsRelativeToDaytime async {
- // setup vars
- List<List<int>> allDiaValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
- List<List<int>> allSysValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
- List<List<int>> allPulValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
-
- // sort all data
- final dbRes = await _database.query('bloodPressureModel', columns: ['*']);
- for (var entry in dbRes) {
- DateTime ts = DateTime.fromMillisecondsSinceEpoch(entry['timestamp'] as int);
- allDiaValuesRelativeToTime[ts.hour].add(entry['diastolic'] as int);
- allSysValuesRelativeToTime[ts.hour].add(entry['systolic'] as int);
- allPulValuesRelativeToTime[ts.hour].add(entry['pulse'] as int);
- }
- for(int i = 0; i < 24; i++) {
- if (allDiaValuesRelativeToTime[i].isEmpty) {
- allDiaValuesRelativeToTime[i].add(await avgDia);
- }
- if (allSysValuesRelativeToTime[i].isEmpty) {
- allSysValuesRelativeToTime[i].add(await avgSys);
- }
- if (allPulValuesRelativeToTime[i].isEmpty) {
- allPulValuesRelativeToTime[i].add(await avgPul);
- }
- }
-
- // make avgs
- List<List<int>> res = [[],[],[]];
- for(int i = 0; i < 24; i++) {
- res[0].add(allDiaValuesRelativeToTime[i].average.toInt());
- res[1].add(allSysValuesRelativeToTime[i].average.toInt());
- res[2].add(allPulValuesRelativeToTime[i].average.toInt());
- }
- return res;
- }
-
Future<void> save(void Function(bool success, String? msg) callback, {bool exportAsText = false}) async {
// create csv
String csvData = 'timestampUnixMs, systolic, diastolic, pulse, notes\n';
@@ -305,6 +221,14 @@ class BloodPressureModel extends ChangeNotifier {
void close() {
_database.close();
}
+
+ int? _toInt(Object? v) {
+ try {
+ return (v as int?);
+ } catch (e) {
+ return (v as double?)?.toInt();
+ }
+ }
}
@immutable
lib/model/blood_pressure_analyzer.dart
@@ -0,0 +1,62 @@
+import 'package:blood_pressure_app/model/blood_pressure.dart';
+
+class BloodPressureAnalyser {
+ final BloodPressureModel _model;
+
+ BloodPressureAnalyser(this._model);
+
+ Future<int> get measurementsPerDay async {
+ final c = await _model.count;
+ final firstDay = await _model.firstDay;
+ final lastDay = await _model.lastDay;
+
+ if (c <= 1 || firstDay.millisecondsSinceEpoch == -1 ||
+ lastDay.millisecondsSinceEpoch == -1) {
+ return -1;
+ }
+ if (lastDay.difference(firstDay).inDays <= 0) {
+ return c;
+ }
+
+ return c ~/ lastDay.difference(firstDay).inDays;
+ }
+
+
+ /// outer list is type (0 -> diastolic, 1 -> systolic, 2 -> pulse)
+ /// inner list index is hour of day ([0] -> 00:00-00:59; [1] -> ...)
+ Future<List<List<int>>> get allAvgsRelativeToDaytime async {
+ // setup vars
+ List<List<int>> allDiaValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
+ List<List<int>> allSysValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
+ List<List<int>> allPulValuesRelativeToTime = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]];
+
+ // sort all data
+ final dbRes = await _database.query('bloodPressureModel', columns: ['*']);
+ for (var entry in dbRes) {
+ DateTime ts = DateTime.fromMillisecondsSinceEpoch(entry['timestamp'] as int);
+ allDiaValuesRelativeToTime[ts.hour].add(entry['diastolic'] as int);
+ allSysValuesRelativeToTime[ts.hour].add(entry['systolic'] as int);
+ allPulValuesRelativeToTime[ts.hour].add(entry['pulse'] as int);
+ }
+ for(int i = 0; i < 24; i++) {
+ if (allDiaValuesRelativeToTime[i].isEmpty) {
+ allDiaValuesRelativeToTime[i].add(await avgDia);
+ }
+ if (allSysValuesRelativeToTime[i].isEmpty) {
+ allSysValuesRelativeToTime[i].add(await avgSys);
+ }
+ if (allPulValuesRelativeToTime[i].isEmpty) {
+ allPulValuesRelativeToTime[i].add(await avgPul);
+ }
+ }
+
+ // make avgs
+ List<List<int>> res = [[],[],[]];
+ for(int i = 0; i < 24; i++) {
+ res[0].add(allDiaValuesRelativeToTime[i].average.toInt());
+ res[1].add(allSysValuesRelativeToTime[i].average.toInt());
+ res[2].add(allPulValuesRelativeToTime[i].average.toInt());
+ }
+ return res;
+ }
+}
\ No newline at end of file
test/model/bood_pressure_test.dart
@@ -31,7 +31,6 @@ void main() {
test('should start empty', () async {
var m = await BloodPressureModel.create(dbPath: '/tmp/bp_test/should_start_empty');
- expect((await m.getLastX(100)).length, 0);
expect((await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).length, 0);
});
@@ -56,7 +55,7 @@ void main() {
var r = BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(31415926), -172, 10000, 0, "((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈๏ แผ่นดินฮั่นเABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ–—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвг, \n \t д∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა");
m.addListener(() async {
- var res = (await m.getLastX(1)).first;
+ var res = (await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).first;
expect(res, isNotNull);
expect(res.creationTime, r.creationTime);
expect(res.systolic, r.systolic);
@@ -75,7 +74,7 @@ void main() {
await m.add(r);
var m2 = await BloodPressureModel.create(dbPath: '/tmp/bp_test/should_store_between_sessions');
- var res = (await m2.getLastX(1)).first;
+ var res = (await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).first;
expect(res.creationTime, r.creationTime);
expect(res.systolic, r.systolic);
@@ -98,12 +97,12 @@ void main() {
var m = await BloodPressureModel.create(dbPath: '/tmp/bp_test/should_delete');
await m.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(758934), 123, 87, 65, ';)'));
- expect((await m.getLastX(100)).length, 1);
+ expect((await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).length, 1);
expect((await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).length, 1);
await m.delete(DateTime.fromMillisecondsSinceEpoch(758934));
- expect((await m.getLastX(100)).length, 0);
+ expect((await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).length, 0);
expect((await m.getInTimeRange(DateTime.fromMillisecondsSinceEpoch(0), DateTime.now())).length, 0);
});