8000 fix(cbio): name the sensor counter a counter, not a clock by shroominic · Pull Request #171 · shroominic/OpenGlucose · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/cgm_cbio/lib/src/cbio_frames.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ final class CbioPackedRecord {
});

final int index;

/// Epoch-less per-record counter: the batch base plus 60 per record.
///
/// It is the sensor's own position, not Unix time. Never render it as a
/// clock and never build a `DateTime` from it.
final int rawTime;
final int reindex;
final int rawGlucose;
Expand Down
19 changes: 16 additions & 3 deletions packages/cgm_cbio/lib/src/cbio_history_archive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ final class CbioRawGlucoseRecord {

final int index;

/// Sensor-recorded epoch seconds, from the batch base plus 60 s per record.
/// Epoch-less sensor counter: the batch base plus 60 per record.
///
/// This is the sensor's own position, not Unix time. It advances exactly one
/// step per stored record, so a surface that renders it as `HH:mm` reports
/// the ingest position and calls it a wall clock. No clock can be derived
/// from it without the sensor's activation time.
final int rawTime;

final int reindex;
Expand Down Expand Up @@ -102,8 +107,16 @@ final class CbioHistoryArchive {
/// True when the archive covers every index between its ends.
bool get contiguous => !_gapDetected;

int? get oldestTime => _byIndex.isEmpty ? null : records.first.rawTime;
int? get newestTime => _byIndex.isEmpty ? null : records.last.rawTime;
/// Lowest sensor counter in the archive, or null when it is empty.
///
/// Named for what it is. A time-shaped name invites a caller to build a
/// `DateTime` from it, which is the defect this rename closes.
int? get oldestSensorCounter =>
_byIndex.isEmpty ? null : records.first.rawTime;

/// Highest sensor counter in the archive, or null when it is empty.
int? get newestSensorCounter =>
_byIndex.isEmpty ? null : records.last.rawTime;

/// Ingests one notification payload, masked or already unmasked by the caller.
CbioArchiveIngestStatus ingest(List<int> frame) {
Expand Down
23 changes: 20 additions & 3 deletions packages/cgm_cbio/test/cbio_history_archive_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,25 @@ void main() {
expect(archive.length, 6);
expect([archive.oldestIndex, archive.newestIndex], [1, 6]);
expect(archive.contiguous, isTrue);
expect(archive.oldestTime, 1000);
expect(archive.newestTime, 1180 + 120);
expect(archive.oldestSensorCounter, 1000);
expect(archive.newestSensorCounter, 1180 + 120);
});

test('the sensor counter is a record position, never a wall clock', () {
final archive = CbioHistoryArchive();
archive.ingest(_rawBatch(first: 1, count: 3, baseTime: 1000));
archive.ingest(_rawBatch(first: 4, count: 3, baseTime: 1180));

// The counter advances one step per stored record, so its span tracks the
// record count and says nothing about elapsed wall time.
expect(
archive.newestSensorCounter! - archive.oldestSensorCounter!,
60 * (archive.length - 1),
);
// A time-shaped name would invite a caller to build a DateTime; both are
// gone.
expect(() => (archive as dynamic).oldestTime, throwsNoSuchMethodError);
expect(() => (archive as dynamic).newestTime, throwsNoSuchMethodError);
});

test('flags a gap when a batch starts past the newest index', () {
Expand Down Expand Up @@ -144,7 +161,7 @@ void main() {
expect(archive.length, 0);
expect(archive.oldestIndex, isNull);
expect(archive.newestIndex, isNull);
expect(archive.oldestTime, isNull);
expect(archive.oldestSensorCounter, isNull);
expect(archive.batchCounts, isEmpty);
});

Expand Down
Loading
0