Skip to content

Commit

Permalink
feat(harmonizer): implement merging algorithm for release group types
Browse files Browse the repository at this point in the history
This keeps only a single primary type and sorts the result.
  • Loading branch information
phw committed Jul 3, 2024
1 parent 0f08a80 commit d9db1f1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 5 deletions.
7 changes: 3 additions & 4 deletions harmonizer/merge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { immutableReleaseProperties, immutableTrackProperties } from './properties.ts';
import { sortTypes } from './release_types.ts';
import { mergeTypes } from './release_types.ts';
import { cloneInto, copyTo, filterErrorEntries, isFilled, uniqueMappedValues } from '@/utils/record.ts';
import { similarNames } from '@/utils/similarity.ts';
import { trackCountSummary } from '@/utils/tracklist.ts';
Expand Down Expand Up @@ -125,10 +125,9 @@ export function mergeRelease(
mergedRelease.info.providers.push(...sourceRelease.info.providers);
mergedRelease.info.messages.push(...sourceRelease.info.messages);

// Merge types
// Merge release group types
if (sourceRelease.types) {
// FIXME: Provide better merge algorithm
mergedRelease.types = sortTypes(new Set(mergedRelease.types).union(new Set(sourceRelease.types)));
mergedRelease.types = mergeTypes(mergedRelease.types || [], sourceRelease.types);
}

// combine availabilities
Expand Down
13 changes: 12 additions & 1 deletion harmonizer/release_types.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { guessLiveRelease, guessTypesForRelease, guessTypesFromTitle, sortTypes } from './release_types.ts';
import { guessLiveRelease, guessTypesForRelease, guessTypesFromTitle, mergeTypes, sortTypes } from './release_types.ts';
import { HarmonyRelease, HarmonyTrack, ReleaseGroupType } from './types.ts';

import { assertEquals } from 'std/assert/assert_equals.ts';
Expand Down Expand Up @@ -87,6 +87,17 @@ describe('release types', () => {
assertEquals(sortedTypes, ['EP', 'Compilation', 'Live', 'Remix']);
});
});

describe('merge types', () => {
it('should reduce to a sorted list with a single primary type', () => {
const mergedTypes = mergeTypes(
['Live', 'Album'],
['Single', 'Compilation', 'Live'],
['EP'],
);
assertEquals(mergedTypes, ['EP', 'Compilation', 'Live']);
});
});
});

function makeRelease(
Expand Down
39 changes: 39 additions & 0 deletions harmonizer/release_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,47 @@ export function sortTypes(types: Iterable<ReleaseGroupType>): ReleaseGroupType[]
});
}

/** Takes several lists of types and returns a single array of unique, sorted types.
*
* The result is reduced to unique elements with only a single primary type.
*/
export function mergeTypes(...typeLists: Array<ReleaseGroupType>[]): ReleaseGroupType[] {
const primaryTypes = new Set<ReleaseGroupType>();
const resultTypes = new Set<ReleaseGroupType>();
typeLists.forEach((types) => {
types.forEach((type) => {
if (isPrimaryType(type)) {
primaryTypes.add(type);
} else {
resultTypes.add(type);
}
});
});
if (primaryTypes.size) {
resultTypes.add(reducePrimaryTypes(Array.from(primaryTypes)));
}
return sortTypes(resultTypes);
}

const primaryTypes = Object.keys(primaryTypeIds);

function isPrimaryType(type: ReleaseGroupType): boolean {
return primaryTypes.includes(type);
}

/** Reduce a list of primary */
function reducePrimaryTypes(types: Array<ReleaseGroupType>): ReleaseGroupType {
return types.reduce((previous, current) => {
if (previous == 'Album' || previous == 'Other') {
// Prefer more specific types over Album or Other. Many providers use Album
// as the generic type.
return current;
} else if (previous == 'Single' && current == 'EP') {
// Prefer EP over Single
return current;
}

// No specific preference, just use the first type found.
return previous;
});
}

0 comments on commit d9db1f1

Please sign in to comment.