// PersonEntity represents information about a Person in the context of FaceClustering that is stored. // On the remote server, the PersonEntity is stored as {Entity} with type person. // On the device, this information is stored as [LocalEntityData] with type person. import "package:flutter/foundation.dart"; class PersonEntity { final String remoteID; final PersonData data; PersonEntity( this.remoteID, this.data, ); // copyWith PersonEntity copyWith({ String? remoteID, PersonData? data, }) { return PersonEntity( remoteID ?? this.remoteID, data ?? this.data, ); } } class ClusterInfo { final String id; final Set faces; ClusterInfo({ required this.id, required this.faces, }); // toJson Map toJson() => { 'id': id, 'faces': faces.toList(), }; // from Json factory ClusterInfo.fromJson(Map json) { return ClusterInfo( id: json['id'] as String, faces: (json['faces'] as List).map((e) => e as String).toSet(), ); } } class PersonData { final String name; final bool isHidden; String? avatarFaceID; List? assigned = List.empty(); List? rejected = List.empty(); final String? birthDate; bool hasAvatar() => avatarFaceID != null; bool get isIgnored => (name.isEmpty || name == '(hidden)' || name == '(ignored)'); PersonData({ required this.name, this.assigned, this.rejected, this.avatarFaceID, this.isHidden = false, this.birthDate, }); // copyWith PersonData copyWith({ String? name, List? assigned, String? avatarFaceId, bool? isHidden, int? version, String? birthDate, }) { return PersonData( name: name ?? this.name, assigned: assigned ?? this.assigned, avatarFaceID: avatarFaceId ?? this.avatarFaceID, isHidden: isHidden ?? this.isHidden, birthDate: birthDate ?? this.birthDate, ); } void logStats() { if (kDebugMode == false) return; // log number of assigned and rejected clusters and total number of faces in each cluster final StringBuffer sb = StringBuffer(); sb.writeln('Person: $name'); int assignedCount = 0; for (final a in (assigned ?? [])) { assignedCount += a.faces.length; } sb.writeln('Assigned: ${assigned?.length} withFaces $assignedCount'); sb.writeln('Rejected: ${rejected?.length}'); if (assigned != null) { for (var cluster in assigned!) { sb.writeln('Cluster: ${cluster.id} - ${cluster.faces.length}'); } } debugPrint(sb.toString()); } // toJson Map toJson() => { 'name': name, 'assigned': assigned?.map((e) => e.toJson()).toList(), 'rejected': rejected?.map((e) => e.toJson()).toList(), 'avatarFaceID': avatarFaceID, 'isHidden': isHidden, 'birthDate': birthDate, }; // fromJson factory PersonData.fromJson(Map json) { final assigned = (json['assigned'] == null || json['assigned'].length == 0) ? [] : List.from( json['assigned'].map((x) => ClusterInfo.fromJson(x)), ); final rejected = (json['rejected'] == null || json['rejected'].length == 0) ? [] : List.from( json['rejected'].map((x) => ClusterInfo.fromJson(x)), ); return PersonData( name: json['name'] as String, assigned: assigned, rejected: rejected, avatarFaceID: json['avatarFaceID'] as String?, isHidden: json['isHidden'] as bool? ?? false, birthDate: json['birthDate'] as String?, ); } }