// lib/metadata/metadata_normalizer.dart import 'metadata_model.dart'; class MetadataNormalizer { NormalizedMetadata normalize(RawMetadata raw, {String fileName = '', String filePath = ''}) { final title = raw.title.trim(); final artist = raw.artist.trim(); final finalTitle = title.isNotEmpty ? title : _inferTitleFromFileName(fileName); final finalArtist = artist.isNotEmpty ? artist : _inferArtistFromPath(filePath); final finalArtist2 = finalArtist.isNotEmpty ? finalArtist : (raw.performers.isNotEmpty ? raw.performers.first : '未知艺术家'); return NormalizedMetadata( title: finalTitle, artist: finalArtist2, album: raw.album, genres: raw.genres, performers: raw.performers, year: raw.year, trackNumber: raw.trackNumber, trackTotal: raw.trackTotal, discNumber: raw.discNumber, totalDisc: raw.totalDisc, duration: raw.duration, artwork: raw.artwork, ); } String _inferTitleFromFileName(String fileName) { final dotIndex = fileName.lastIndexOf('.'); return dotIndex > 0 ? fileName.substring(0, dotIndex).trim() : fileName.trim(); } String _inferArtistFromPath(String filePath) { final parts = filePath.split(RegExp(r'[/\\]')); if (parts.length >= 2) { final candidate = parts[parts.length - 2].trim(); if (candidate.isNotEmpty && !candidate.startsWith('http')) { return candidate; } } return '未知艺术家'; } CandidateMetadata evaluate( NormalizedMetadata normalized, List> history) { // 第一版:直接接受,置信度 0.8 return CandidateMetadata( metadata: normalized, confidence: 0.8, evidence: {'normalized': 0.8}, ); } FinalMetadata decide(CandidateMetadata candidate, {double threshold = 0.6}) { return FinalMetadata( title: candidate.metadata.title, artist: candidate.metadata.artist, album: candidate.metadata.album, genre: candidate.metadata.genres.isNotEmpty ? candidate.metadata.genres.first : '', genres: candidate.metadata.genres, performers: candidate.metadata.performers, year: candidate.metadata.year, trackNumber: candidate.metadata.trackNumber, trackTotal: candidate.metadata.trackTotal, discNumber: candidate.metadata.discNumber, totalDisc: candidate.metadata.totalDisc, duration: candidate.metadata.duration, artwork: candidate.metadata.artwork, source: 'normalized', ); } }