@@ -122,7 +122,7 @@ class FitbitService extends IService {
122122 }
123123
124124 final String date = metrics.dateAsString;
125- Map <String , Metrics > cacheMap = {};
125+ Map <String , Metrics ? > cacheMap = {};
126126
127127 try {
128128 cacheMap = await storage.readCache (StorageKeys .cache);
@@ -131,7 +131,7 @@ class FitbitService extends IService {
131131 return cacheMap[date]! ;
132132 }
133133 } catch (e) {
134- _logger.e ("Error reading cache: $e " );
134+ _logger.e ("Fetch - Error reading cache: $e for date: $ date " );
135135 }
136136
137137 _logger.d ("Cache miss for date: $date " );
@@ -151,31 +151,38 @@ class FitbitService extends IService {
151151 if (response.statusCode == 200 ) {
152152 final Map <String , dynamic > data = jsonDecode (response.body);
153153
154- if (data.containsKey ("weight" ) && data["weight" ].isNotEmpty) {
155- final List <Metrics > metricsList =
156- (data['weight' ] as List <dynamic >)
157- .where ((ret) => ret != null )
158- .map <Metrics ?>((ret) {
159- try {
160- final FitBitObject obj = toFitBitObject (ret);
161- return obj.metrics;
162- } catch (_) {
163- return null ;
164- }
165- })
166- .where ((ret) => ret != null )
167- .map ((ret) => ret! )
168- .toList ();
169-
170- final Map <String , Metrics > metricsMap = {
171- for (var metric in metricsList) metric.dateAsString: metric,
172- };
154+ DateTime current = metrics.date;
155+ DateTime cutoff = DateTime (
156+ current.year,
157+ current.month - 1 ,
158+ current.day,
159+ );
173160
161+ Map <String , Metrics ?> metricsMap = {};
162+ if (data.containsKey ("weight" ) && data["weight" ].isNotEmpty) {
163+ Metrics last = metrics;
164+ for (var ret in data['weight' ] as List <dynamic >) {
165+ try {
166+ final FitBitObject obj = toFitBitObject (ret);
167+ metricsMap.putIfAbsent (
168+ obj.metrics.dateAsString,
169+ () => obj.metrics,
170+ );
171+ last = obj.metrics;
172+ } catch (_) {
173+ _logger.e ("Error parsing FitBitObject: $ret " );
174+ }
175+ }
176+
177+ while (current.isAfter (cutoff)) {
178+ final curDate = current.toIso8601String ().split ('T' ).first;
179+ // Placeholder for "failed to parse" or "no data"
180+ metricsMap.putIfAbsent (curDate, () => null );
181+ current = current.subtract (const Duration (days: 1 ));
182+ }
174183 cacheMap.addEntries (metricsMap.entries);
175184 await storage.writeCache (StorageKeys .cache, cacheMap);
176-
177- // Weight data: {bmi: 21.95, date: 2025-03-10, fat: 15.17300033569336, logId: 1741594747000, source: Aria, time: 08:19:07, weight: 80.9}
178- return metricsList.last;
185+ return last;
179186 }
180187 } // Else if token is expired
181188 else if (response.statusCode == 401 ) {
@@ -209,45 +216,56 @@ class FitbitService extends IService {
209216 return ratioPoints;
210217 }
211218
212- final String date = Metrics .defaultMetrics ().dateAsString ;
213- Map < String , Metrics > cacheMap = {} ;
219+ Metrics m = Metrics .defaultMetrics ();
220+ final String date = m.dateAsString ;
214221
215222 try {
216- cacheMap = await storage.readCache (StorageKeys .cache);
217- _logger.d ("Cache hit for date: $date " );
218-
219223 final int offset = switch (period) {
220224 MonthPeriod .one => 1 ,
221225 MonthPeriod .two => 2 ,
222226 MonthPeriod .three => 3 ,
223227 };
224228
225- final DateTime cutoff = DateTime (
226- DateTime .now ().year,
227- DateTime .now ().month - offset,
228- DateTime .now ().day,
229+ DateTime current = m.date;
230+ DateTime cutoff = DateTime (
231+ current.year,
232+ current.month - offset,
233+ current.day,
229234 );
230- final filtered = Map <String , Metrics >.from (cacheMap)
231- ..removeWhere ((k, v) => DateTime .parse (k).isBefore (cutoff));
232235
233- // Get newest Metrics from filtered map
234- final end =
235- filtered.entries
236- .map ((entry) => MapEntry (DateTime .parse (entry.key), entry.value))
237- .reduce ((a, b) => a.key.isAfter (b.key) ? a : b)
238- .value;
236+ Map <String , Metrics ?> cacheMap = await storage.readCache (
237+ StorageKeys .cache,
238+ );
239+ final Map <String , Metrics > filtered = {};
240+ while (current.isAfter (cutoff)) {
241+ final curDate = current.toIso8601String ().split ('T' ).first;
242+ if (cacheMap.containsKey (curDate)) {
243+ if (cacheMap[curDate] != null ) {
244+ filtered[curDate] = cacheMap[curDate]! ;
245+ }
246+ current = current.subtract (const Duration (days: 1 ));
247+ } else {
248+ await fetchMetrics (m.copyWith (date: current));
249+ cacheMap = await storage.readCache (StorageKeys .cache);
250+ }
251+ }
252+
253+ // Get the latest metrics from filtered cacheMap
254+ final Metrics latestDate =
255+ (filtered.values.toList ()..sort ((a, b) => a.date.compareTo (b.date)))
256+ .last;
239257
240258 BfpCalculator bfpCalculator = BfpCalculator ();
241259 ratioPoints =
242260 filtered.entries.map ((entry) {
243- final change = end .difference (entry.value);
261+ final change = latestDate .difference (entry.value);
244262 final ratio = bfpCalculator.getRatio (change);
245263 return RatioPoint (DateTime .parse (entry.key), ratio);
246264 }).toList ();
247265
248266 return ratioPoints;
249267 } catch (e) {
250- _logger.e ("Error reading cache: $e " );
268+ _logger.e ("Ratio - Error reading cache: $e for date: $ date " );
251269 }
252270
253271 _logger.d ("Cache miss for date: $date " );
0 commit comments