From b0640393a7071b82e00be10d43f974b0c27d5673 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 5 May 2022 19:43:57 +1000 Subject: [PATCH 1/2] allow searchign by album and add album to lyrics quality also add tests for this --- Sources/LyricsService/Lyrics+Quality.swift | 38 ++++++++++++++++--- .../LyricsService/LyricsSearchRequest.swift | 6 +-- .../Provider/Discontinued/ViewLyrics.swift | 2 +- Sources/LyricsService/Provider/Gecimi.swift | 2 +- Sources/LyricsService/Provider/Syair.swift | 5 ++- Tests/LyricsKitTests/LyricsKitTests.swift | 15 ++++++++ 6 files changed, 56 insertions(+), 12 deletions(-) diff --git a/Sources/LyricsService/Lyrics+Quality.swift b/Sources/LyricsService/Lyrics+Quality.swift index fe95d42..c22efc5 100644 --- a/Sources/LyricsService/Lyrics+Quality.swift +++ b/Sources/LyricsService/Lyrics+Quality.swift @@ -12,8 +12,10 @@ import LyricsCore private let translationBonus = 0.1 private let inlineTimeTagBonus = 0.1 +private let matchedAlbumFactor = 1.0 private let matchedArtistFactor = 1.3 private let matchedTitleFactor = 1.5 +private let noAlbumFactor = 0.8 private let noArtistFactor = 0.8 private let noTitleFactor = 0.8 private let noDurationFactor = 0.8 @@ -26,7 +28,7 @@ extension Lyrics { if let quality = metadata.quality { return quality } - var quality = 1 - pow((qualityMixBound - artistQuality) * (qualityMixBound - titleQuality) * (qualityMixBound - durationQuality), 0.3333) + var quality = 1 - pow((qualityMixBound - albumQuality) * (qualityMixBound - artistQuality) * (qualityMixBound - titleQuality) * (qualityMixBound - durationQuality), 0.3333) if metadata.hasTranslation { quality += translationBonus } @@ -39,13 +41,19 @@ extension Lyrics { public func isMatched() -> Bool { guard let artist = idTags[.artist], - let title = idTags[.title] else { + let title = idTags[.title], + let album = idTags[.album] else { return false } switch metadata.searchRequest?.searchTerm { - case let .info(searchTitle, searchArtist)?: - return title.isCaseInsensitiveSimilar(to: searchTitle) + case let .info(searchTitle, searchArtist, searchAlbum)?: + let caseInsensitiveMatch = title.isCaseInsensitiveSimilar(to: searchTitle) && artist.isCaseInsensitiveSimilar(to: searchArtist) + if let searchAlbum = searchAlbum { + return caseInsensitiveMatch && album.isCaseInsensitiveSimilar(to: searchAlbum) + } else { + return caseInsensitiveMatch + } case let .keyword(keyword)?: return title.isCaseInsensitiveSimilar(to: keyword) && artist.isCaseInsensitiveSimilar(to: keyword) @@ -53,11 +61,29 @@ extension Lyrics { return false } } + + private var albumQuality: Double { + guard let album = idTags[.album] else { return noAlbumFactor } + switch metadata.searchRequest?.searchTerm { + case let .info(_, _, searchAlbum)?: + if album == searchAlbum { return matchedAlbumFactor } + if let searchAlbum = searchAlbum { + return similarity(s1: album, s2: searchAlbum) + } else { + return 1 - qualityMixBound + } + case let .keyword(keyword)?: + if keyword.contains(album) { return matchedAlbumFactor } + return similarity(s1: album, in: keyword) + case nil: + return noAlbumFactor + } + } private var artistQuality: Double { guard let artist = idTags[.artist] else { return noArtistFactor } switch metadata.searchRequest?.searchTerm { - case let .info(_, searchArtist)?: + case let .info(_, searchArtist, _)?: if artist == searchArtist { return matchedArtistFactor } return similarity(s1: artist, s2: searchArtist) case let .keyword(keyword)?: @@ -71,7 +97,7 @@ extension Lyrics { private var titleQuality: Double { guard let title = idTags[.title] else { return noTitleFactor } switch metadata.searchRequest?.searchTerm { - case let .info(searchTitle, _)?: + case let .info(searchTitle, _, _)?: if title == searchTitle { return matchedTitleFactor } return similarity(s1: title, s2: searchTitle) case let .keyword(keyword)?: diff --git a/Sources/LyricsService/LyricsSearchRequest.swift b/Sources/LyricsService/LyricsSearchRequest.swift index df42bf4..34179a2 100644 --- a/Sources/LyricsService/LyricsSearchRequest.swift +++ b/Sources/LyricsService/LyricsSearchRequest.swift @@ -18,7 +18,7 @@ public struct LyricsSearchRequest: Equatable { public enum SearchTerm: Equatable { case keyword(String) - case info(title: String, artist: String) + case info(title: String, artist: String, album: String? = nil) } public init(searchTerm: SearchTerm, duration: TimeInterval, limit: Int = 6, userInfo: [String: String] = [:]) { @@ -35,8 +35,8 @@ extension LyricsSearchRequest.SearchTerm: CustomStringConvertible { switch self { case let .keyword(keyword): return keyword - case let .info(title: title, artist: artist): - return title + " " + artist + case let .info(title: title, artist: artist, album: album): + return title + " " + artist + (album != nil ? " \(album!)" : "") } } } diff --git a/Sources/LyricsService/Provider/Discontinued/ViewLyrics.swift b/Sources/LyricsService/Provider/Discontinued/ViewLyrics.swift index a8db33d..6e6ecc6 100644 --- a/Sources/LyricsService/Provider/Discontinued/ViewLyrics.swift +++ b/Sources/LyricsService/Provider/Discontinued/ViewLyrics.swift @@ -46,7 +46,7 @@ extension LyricsProviders.ViewLyrics: _LyricsProvider { } public func lyricsSearchPublisher(request: LyricsSearchRequest) -> AnyPublisher { - guard case let .info(title, artist) = request.searchTerm else { + guard case let .info(title, artist, _) = request.searchTerm else { // cannot search by keyword return Empty().eraseToAnyPublisher() } diff --git a/Sources/LyricsService/Provider/Gecimi.swift b/Sources/LyricsService/Provider/Gecimi.swift index 7d7aaf1..3a2fe23 100644 --- a/Sources/LyricsService/Provider/Gecimi.swift +++ b/Sources/LyricsService/Provider/Gecimi.swift @@ -34,7 +34,7 @@ extension LyricsProviders.Gecimi: _LyricsProvider { public static let service: LyricsProviders.Service? = .gecimi public func lyricsSearchPublisher(request: LyricsSearchRequest) -> AnyPublisher { - guard case let .info(title, artist) = request.searchTerm else { + guard case let .info(title, artist, _) = request.searchTerm else { // cannot search by keyword return Empty().eraseToAnyPublisher() } diff --git a/Sources/LyricsService/Provider/Syair.swift b/Sources/LyricsService/Provider/Syair.swift index a9d7da9..cc8a3ca 100644 --- a/Sources/LyricsService/Provider/Syair.swift +++ b/Sources/LyricsService/Provider/Syair.swift @@ -30,9 +30,12 @@ extension LyricsProviders.Syair: _LyricsProvider { public func lyricsSearchPublisher(request: LyricsSearchRequest) -> AnyPublisher { var parameter: [String: Any] = ["page": 1] switch request.searchTerm { - case let .info(title: title, artist: artist): + case let .info(title: title, artist: artist, album: album): parameter["artist"] = artist parameter["title"] = title + if let album = album { + parameter["album"] = album + } case let .keyword(keyword): parameter["q"] = keyword } diff --git a/Tests/LyricsKitTests/LyricsKitTests.swift b/Tests/LyricsKitTests/LyricsKitTests.swift index a4e98e8..caeafcf 100644 --- a/Tests/LyricsKitTests/LyricsKitTests.swift +++ b/Tests/LyricsKitTests/LyricsKitTests.swift @@ -40,4 +40,19 @@ final class LyricsKitTests: XCTestCase { waitForExpectations(timeout: 10) cancelable.cancel() } + + func testNetEaseAlbumSearch() { + let searchResultEx = expectation(description: "search succeed") + let provider = LyricsProviders.NetEase() + let searchTerm = LyricsSearchRequest.SearchTerm.info(title: "Cocoa Hooves", artist: "Glass Animals", album: "ZABA") + let publisher = provider.lyricsPublisher(request: .init(searchTerm: searchTerm, duration: 271)) + let cancelable = publisher.sink { lyrics in + guard case let .info(title, artist, album) = searchTerm else { return } + if lyrics.idTags[.title] == title && lyrics.idTags[.artist] == artist && lyrics.idTags[.album] == album { + searchResultEx.fulfill() + } + } + waitForExpectations(timeout: 10) + cancelable.cancel() + } } From cf4019fd666fb49c81b1c7850e6775f7cf09e690 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 5 May 2022 22:20:45 +1000 Subject: [PATCH 2/2] fix calculation order --- Sources/LyricsService/Lyrics+Quality.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/LyricsService/Lyrics+Quality.swift b/Sources/LyricsService/Lyrics+Quality.swift index c22efc5..b3a1572 100644 --- a/Sources/LyricsService/Lyrics+Quality.swift +++ b/Sources/LyricsService/Lyrics+Quality.swift @@ -70,7 +70,7 @@ extension Lyrics { if let searchAlbum = searchAlbum { return similarity(s1: album, s2: searchAlbum) } else { - return 1 - qualityMixBound + return qualityMixBound - 1 } case let .keyword(keyword)?: if keyword.contains(album) { return matchedAlbumFactor }