class Shot { final String id; final double x; // Relative position (0.0 - 1.0) final double y; // Relative position (0.0 - 1.0) final int score; final String sessionId; Shot({ required this.id, required this.x, required this.y, required this.score, required this.sessionId, }); Shot copyWith({ String? id, double? x, double? y, int? score, String? sessionId, }) { return Shot( id: id ?? this.id, x: x ?? this.x, y: y ?? this.y, score: score ?? this.score, sessionId: sessionId ?? this.sessionId, ); } Map toMap() { return { 'id': id, 'x': x, 'y': y, 'score': score, 'session_id': sessionId, }; } factory Shot.fromMap(Map map) { return Shot( id: map['id'] as String, x: (map['x'] as num).toDouble(), y: (map['y'] as num).toDouble(), score: map['score'] as int, sessionId: map['session_id'] as String, ); } @override String toString() { return 'Shot(id: $id, x: $x, y: $y, score: $score, sessionId: $sessionId)'; } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is Shot && other.id == id && other.x == x && other.y == y && other.score == score && other.sessionId == sessionId; } @override int get hashCode { return id.hashCode ^ x.hashCode ^ y.hashCode ^ score.hashCode ^ sessionId.hashCode; } }