Commit 5327983
Changed files (9)
health_data_store
health_data_store/lib/src/repositories/blood_pressure_repository.dart
@@ -0,0 +1,86 @@
+import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/database_helper.dart';
+import 'package:health_data_store/src/database_manager.dart';
+import 'package:health_data_store/src/repositories/repository.dart';
+import 'package:sqflite_common/sqflite.dart';
+
+/// Repository for [BloodPressureRecord]s.
+///
+/// Provides high level access on [BloodPressureRecord]s saved in a
+/// [DatabaseManager] managed database. Allows to store and query records.
+class BloodPressureRepository extends Repository<BloodPressureRecord> {
+ /// Create [BloodPressureRecord] repository.
+ BloodPressureRepository(this._db);
+
+ /// The [DatabaseManager] managed database
+ final Database _db;
+
+ @override
+ Future<void> add(BloodPressureRecord record) async{
+ assert(record.sys != null || record.dia != null || record.pul != null,
+ "Adding records that don't contain values(sys,dia,pul) can't be accessed"
+ 'and should therefore not be added to the repository.');
+ final timeSec = record.time.millisecondsSinceEpoch ~/ 1000;
+ await _db.transaction((txn) async {
+ final entryID = await DBHelper.getEntryID(
+ txn,
+ timeSec,
+ ['Systolic', 'Diastolic', 'Pulse'],
+ );
+ print(record);
+ if (record.sys != null) {
+ await txn.insert('Systolic', {
+ 'entryID': entryID,
+ 'sys': record.sys,
+ });
+ }
+ if (record.dia != null) {
+ await txn.insert('Diastolic', {
+ 'entryID': entryID,
+ 'dia': record.dia,
+ });
+ }
+ if (record.pul != null) {
+ await txn.insert('Pulse', {
+ 'entryID': entryID,
+ 'pul': record.pul,
+ });
+ }
+ });
+ }
+
+ @override
+ Future<List<BloodPressureRecord>> get(DateRange range) async {
+ final results = await _db.rawQuery(
+ 'SELECT timestampUnixS, sys, dia, pul '
+ 'FROM Timestamps AS t '
+ 'LEFT JOIN Systolic AS s ON t.entryID = s.entryID '
+ 'LEFT JOIN Diastolic AS d ON t.entryID = d.entryID '
+ 'LEFT JOIN Pulse AS p ON t.entryID = p.entryID '
+ 'WHERE timestampUnixS BETWEEN ? AND ?;',
+ [range.startStamp, range.endStamp]
+ );
+ final records = <BloodPressureRecord>[];
+ for (final r in results) {
+ final timeS = r['timestampUnixS'] as int;
+ final newRec = BloodPressureRecord(
+ time: DateTime.fromMillisecondsSinceEpoch(timeS * 1000),
+ sys: r['sys'] as int?,
+ dia: r['dia'] as int?,
+ pul: r['pul'] as int?,
+ );
+ if (newRec.sys !=null || newRec.dia != null || newRec.pul != null) {
+ records.add(newRec);
+ }
+ }
+
+ return records;
+ }
+
+ @override
+ Future<void> remove(BloodPressureRecord value) async {
+ // TODO: implement remove
+ throw UnimplementedError();
+ }
+
+}
health_data_store/lib/src/repositories/repository.dart
@@ -1,5 +1,3 @@
-import 'dart:collection';
-
import 'package:health_data_store/src/database_manager.dart';
import 'package:health_data_store/src/types/date_range.dart';
@@ -18,5 +16,5 @@ abstract class Repository<T> {
Future<void> remove(T value);
/// Inclusively returns all values in the specified [range].
- Future<UnmodifiableListView<T>> get(DateRange range);
+ Future<List<T>> get(DateRange range);
}
health_data_store/lib/src/database_helper.dart
@@ -42,7 +42,7 @@ class DBHelper {
Transaction txn,
int startUnixS,
int endUnixS,
- ) async {
+ ) async { // TODO: consider removing, once unused
final result = await txn.query('Timestamps',
columns: ['entryID'],
where: 'timestampUnixS BETWEEN ? AND ?',
health_data_store/lib/src/database_manager.dart
@@ -50,10 +50,14 @@ class DatabaseManager {
'FOREIGN KEY("entryID") REFERENCES "Timestamps"("entryID"),'
'FOREIGN KEY("medID") REFERENCES "Medicine"("medID")'
');');
- for (final intTable in ['Systolic', 'Diastolic', 'Pulse']) {
- await _db.execute('CREATE TABLE "$intTable" ('
+ for (final info in [
+ ('Systolic','sys'),
+ ('Diastolic', 'dia'),
+ ('Pulse','pul')
+ ]) {
+ await _db.execute('CREATE TABLE "${info.$1}" ('
'"entryID" INTEGER NOT NULL,'
- '"value" INTEGER,'
+ '"${info.$2}" INTEGER,'
'FOREIGN KEY("entryID") REFERENCES "Timestamps"("entryID"),'
'PRIMARY KEY("entryID")'
');');
health_data_store/test/src/repositories/blood_pressure_repository_test.dart
@@ -0,0 +1,43 @@
+
+import 'package:health_data_store/health_data_store.dart';
+import 'package:health_data_store/src/repositories/blood_pressure_repository.dart';
+import 'package:test/test.dart';
+
+import '../database_manager_test.dart';
+import '../types/blood_pressure_record_test.dart';
+
+void main() {
+ sqfliteTestInit();
+ test('should initialize', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ BloodPressureRepository(db.db);
+ });
+ test('should store records without errors', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = BloodPressureRepository(db.db);
+ await repo.add(mockRecord(sys: 123, dia: 456, pul: 789));
+ await repo.add(mockRecord(sys: 123, pul: 789));
+ await repo.add(mockRecord(sys: 123));
+ expect(() async => repo.add(mockRecord()), throwsA(isA<AssertionError>()));
+ });
+ test('should return stored records', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = BloodPressureRepository(db.db);
+ final r1 = mockRecord(time: 50000, sys: 123);
+ final r2 = mockRecord(time: 80000, sys: 456, dia: 457, pul: 458);
+ final r3 = mockRecord(time: 20000, sys: 788, pul: 789);
+ await repo.add(r1);
+ await repo.add(r2);
+ await repo.add(r3);
+
+ final values = await repo.get(DateRange(
+ start: DateTime.fromMillisecondsSinceEpoch(20000),
+ end: DateTime.fromMillisecondsSinceEpoch(80000),
+ ));
+ expect(values, hasLength(3));
+ expect(values, containsAll([r1,r2,r3]));
+ });
+}
health_data_store/test/src/types/blood_pressure_record_test.dart
@@ -39,3 +39,15 @@ void main() {
))));
});
}
+
+BloodPressureRecord mockRecord({
+ int? time,
+ int? sys,
+ int? dia,
+ int? pul,
+}) => BloodPressureRecord(
+ time: time!=null ? DateTime.fromMillisecondsSinceEpoch(time) : DateTime.now(),
+ sys: sys,
+ dia: dia,
+ pul: pul,
+);
health_data_store/test/src/database_helper_test.dart
@@ -54,7 +54,7 @@ void main() {
expect(entry1, 1);
await txn.insert('Systolic', {
'entryID': entry1,
- 'value': 1,
+ 'sys': 1,
});
final anotherEntry = await DBHelper.getEntryID(txn, 123, ['Systolic']);
expect(anotherEntry, 2);
health_data_store/test/src/database_manager_test.dart
@@ -14,24 +14,18 @@ void sqfliteTestInit() {
void main() {
sqfliteTestInit();
test('should initialize without issues', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
expect(db.db.isOpen, isTrue);
});
test('should close', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
expect(db.db.isOpen, isTrue);
await db.close();
expect(db.db.isOpen, isFalse);
});
test('should setup medicine table', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
final result = await db.db
@@ -93,9 +87,7 @@ void main() {
throwsException);
});
test('should create timestamps table correctly', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
await db.db.insert('Timestamps', {
'entryID': 1,
@@ -115,9 +107,7 @@ void main() {
}), throwsException);
});
test('should create intake table correctly', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
await db.db.insert('Intake', {
@@ -130,28 +120,28 @@ void main() {
expect(data.first.keys, hasLength(3));
});
test('should create timestamps sys,dia,pul tables correctly', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
- for (final t in ['Systolic', 'Diastolic', 'Pulse']) {
- await db.db.insert(t, {
+ for (final t in [
+ ('Systolic','sys'),
+ ('Diastolic', 'dia'),
+ ('Pulse','pul')
+ ]) {
+ await db.db.insert(t.$1, {
'entryID': 1,
- 'value': 1,
+ t.$2: 1,
});
- await db.db.insert(t, {
+ await db.db.insert(t.$1, {
'entryID': 2,
- 'value': null,
+ t.$2: null,
});
- final data = await db.db.query(t);
+ final data = await db.db.query(t.$1);
expect(data, hasLength(2));
expect(data.first.keys, hasLength(2));
}
});
test('should create notes table correctly', () async {
- final db = await DatabaseManager.load(await openDatabase(
- inMemoryDatabasePath,
- ));
+ final db = await mockDBManager();
addTearDown(db.close);
await db.db.insert('Notes', {
@@ -165,3 +155,6 @@ void main() {
expect(data.first['color'], equals(0xFF990098));
});
}
+
+Future<DatabaseManager> mockDBManager() async => DatabaseManager.load(
+ await openDatabase(inMemoryDatabasePath));
health_data_store/test/src/health_data_store_test.dart
@@ -2,5 +2,6 @@
void main() {
-
+ // TODO: implement
+ throw UnimplementedError('TODO');
}