pk_data_mapper.dart 2.61 KB
import '../../../../data/models/health/health_models.dart';
import 'pk_data.dart';

/// The existing PK endpoint compares the signed-in user with their partner.
/// Its partner fields belong on the left, user fields on the right.
PkData mapPartnerPkData(
  PkCurrentMonthData source, {
  required PkPlayer partner,
  required PkPlayer self,
  required DateTime now,
}) {
  final todayDate = pkRecordDate(source.todayRecord?.date);
  final today = todayDate == null ||
          (todayDate.year == now.year &&
              todayDate.month == now.month &&
              todayDate.day == now.day)
      ? source.todayRecord
      : null;
  final days = <int, PkDay>{};
  for (final record in source.monthRecordList ?? const <PkRecord>[]) {
    final date = pkRecordDate(record.date);
    if (date == null ||
        date.year != now.year ||
        date.month != now.month ||
        date.day > now.day ||
        record.partnerScore == null ||
        record.userScore == null) {
      continue;
    }
    days[date.day] = PkDay(record.partnerScore!, record.userScore!);
  }
  if (today?.partnerScore != null && today?.userScore != null) {
    days[now.day] = PkDay(today!.partnerScore!, today.userScore!);
  }
  return PkData(
    month: DateTime(now.year, now.month),
    days: days,
    left: PkPlayer(
      name: partner.name,
      subtitle: partner.subtitle,
      avatarUrl: partner.avatarUrl,
      avatarAsset: partner.avatarAsset,
      score: today?.partnerScore,
      steps: today?.partnerSteps ?? partner.steps,
      calories: today?.partnerMove ?? partner.calories,
      standingHours: today?.partnerStand?.toDouble(),
      winningDays: source.partnerWinAmount,
    ),
    right: PkPlayer(
      name: self.name,
      subtitle: self.subtitle,
      avatarUrl: self.avatarUrl,
      avatarAsset: self.avatarAsset,
      score: today?.userScore,
      steps: today?.userSteps ?? self.steps,
      calories: today?.userMove ?? self.calories,
      standingHours: today?.userStand?.toDouble(),
      winningDays: source.userWinAmount,
    ),
  );
}

/// Accept the date encodings used by health records: yyyyMMdd or Unix time.
DateTime? pkRecordDate(int? value) {
  if (value == null || value <= 0) return null;
  if (value >= 10000101 && value <= 99991231) {
    final year = value ~/ 10000, month = value ~/ 100 % 100, day = value % 100;
    final date = DateTime(year, month, day);
    return date.year == year && date.month == month && date.day == day
        ? date
        : null;
  }
  if (value < 1000000000 || value > 8640000000000000) return null;
  return DateTime.fromMillisecondsSinceEpoch(
    value >= 1000000000000 ? value : value * 1000,
  );
}