diff --git a/harmonizer/merge.ts b/harmonizer/merge.ts index 21c536a..392681e 100644 --- a/harmonizer/merge.ts +++ b/harmonizer/merge.ts @@ -18,6 +18,7 @@ import type { ProviderPreferences, ProviderReleaseErrorMap, ProviderReleaseMap, + ReleaseGroupType, ResolvableEntity, } from './types.ts'; @@ -85,6 +86,9 @@ export function mergeRelease( const availableRegions = new Set(); const excludedRegions = new Set(); + // temporary list of all release group types + const releaseGroupTypes = new Array>(); + orderByPreference(availableProviders, preferredProviders); // Phase 1: Clone properties without specific provider preferences @@ -127,7 +131,7 @@ export function mergeRelease( // Merge release group types if (sourceRelease.types) { - mergedRelease.types = mergeTypes(mergedRelease.types || [], sourceRelease.types); + releaseGroupTypes.push(sourceRelease.types); } // combine availabilities @@ -143,8 +147,9 @@ export function mergeRelease( }); } - // Extend the types with types guessed from titles - guessTypesForRelease(mergedRelease); + // guess types from titles and merge all release types + releaseGroupTypes.push(guessTypesForRelease(mergedRelease)); + mergedRelease.types = mergeTypes(...releaseGroupTypes); // assign temporary sets to the merge target if (availableRegions.size) { diff --git a/harmonizer/release_types.test.ts b/harmonizer/release_types.test.ts index 9c7125a..68a8721 100644 --- a/harmonizer/release_types.test.ts +++ b/harmonizer/release_types.test.ts @@ -28,8 +28,8 @@ describe('release types', () => { passingCases.forEach(([description, release, expected]) => { it(description, () => { - guessTypesForRelease(release); - assertEquals(release.types, expected); + const guessedTypes = guessTypesForRelease(release); + assertEquals(new Set(guessedTypes), new Set(expected)); }); }); }); diff --git a/harmonizer/release_types.ts b/harmonizer/release_types.ts index 98aa3b6..4f0532f 100644 --- a/harmonizer/release_types.ts +++ b/harmonizer/release_types.ts @@ -2,13 +2,13 @@ import { HarmonyRelease, HarmonyTrack, ReleaseGroupType } from './types.ts'; import { primaryTypeIds } from '@kellnerd/musicbrainz/data/release-group'; /** Guess the types for a release from release and track titles. */ -export function guessTypesForRelease(release: HarmonyRelease) { +export function guessTypesForRelease(release: HarmonyRelease): Iterable { let types = new Set(release.types); types = types.union(guessTypesFromTitle(release.title)); if (!types.has('Live') && guessLiveRelease(release.media.flatMap((media) => media.tracklist))) { types.add('Live'); } - release.types = sortTypes(types); + return types; } const detectTypesPatterns = [ @@ -79,18 +79,18 @@ export function sortTypes(types: Iterable): ReleaseGroupType[] * * The result is reduced to unique elements with only a single primary type. */ -export function mergeTypes(...typeLists: Array[]): ReleaseGroupType[] { +export function mergeTypes(...typeLists: Iterable[]): ReleaseGroupType[] { const primaryTypes = new Set(); const resultTypes = new Set(); - typeLists.forEach((types) => { - types.forEach((type) => { + for (const types of typeLists) { + for (const type of types) { if (isPrimaryType(type)) { primaryTypes.add(type); } else { resultTypes.add(type); } - }); - }); + } + } if (primaryTypes.size) { resultTypes.add(reducePrimaryTypes(Array.from(primaryTypes))); }