import '../native/phash_bindings.dart'; import '../native/phash_loader.dart'; import 'hash_library.dart'; class PhashMatch { const PhashMatch({ required this.cardId, required this.distance, required this.score, this.filename, }); final String cardId; final int distance; final double score; final String? filename; bool get confident => score >= 75; String? get assetPath => filename == null ? null : 'test_assets/$filename'; } /// Hamming ranking over a local hash library. class PhashMatcher { PhashMatcher({PhashNative? native}) : _native = native ?? PhashNative(); final PhashNative _native; static double scoreFromDistance(int distance, {int bits = kPhashBits}) { final raw = 100.0 - (distance / bits) * 100.0; return double.parse(raw.toStringAsFixed(2)); } List topN( String queryHash, HashLibrary library, { int n = 3, }) { if (library.items.isEmpty || n <= 0) return const []; final scored = []; for (final item in library.items) { final distance = _native.hamming(queryHash, item.hash); scored.add( PhashMatch( cardId: item.cardId, distance: distance, score: scoreFromDistance(distance), filename: item.filename, ), ); } scored.sort((a, b) => a.distance.compareTo(b.distance)); if (scored.length <= n) return scored; return scored.sublist(0, n); } }