import 'dart:convert'; import 'dart:io'; class HashEntry { const HashEntry({ required this.cardId, required this.hash, this.filename, }); final String cardId; final String hash; final String? filename; /// Flutter asset path for the gallery image. String? get assetPath => filename == null ? null : 'test_assets/$filename'; } class HashLibrary { const HashLibrary({ required this.version, required this.algorithm, required this.hashBits, required this.items, }); final String version; final String algorithm; final int hashBits; final List items; static HashLibrary fromJson(Map json) { final rawItems = (json['items'] as List? ?? const []); return HashLibrary( version: json['version'] as String? ?? 'assets-v1', algorithm: json['algorithm'] as String? ?? 'rgb-phash-v1', hashBits: json['hash_bits'] as int? ?? 105, items: rawItems .map((e) { final m = e as Map; return HashEntry( cardId: m['card_id'] as String, hash: m['hash'] as String, filename: m['filename'] as String?, ); }) .toList(growable: false), ); } Map toJson() => { 'version': version, 'algorithm': algorithm, 'hash_bits': hashBits, 'card_count': items.length, 'items': items .map( (e) => { 'card_id': e.cardId, 'hash': e.hash, if (e.filename != null) 'filename': e.filename, }, ) .toList(growable: false), }; /// Load from filesystem (CLI scripts / tests). static Future loadFile(String path) async { final text = await File(path).readAsString(); return fromJson(jsonDecode(text) as Map); } Future saveFile(String path) async { final file = File(path); await file.parent.create(recursive: true); const encoder = JsonEncoder.withIndent(' '); await file.writeAsString('${encoder.convert(toJson())}\n'); } }