diff options
Diffstat (limited to 'src/data/composite/things/track')
21 files changed, 427 insertions, 391 deletions
diff --git a/src/data/composite/things/track/index.js b/src/data/composite/things/track/index.js index 714858a0..e789e736 100644 --- a/src/data/composite/things/track/index.js +++ b/src/data/composite/things/track/index.js @@ -1,16 +1,17 @@ export {default as exitWithoutUniqueCoverArt} from './exitWithoutUniqueCoverArt.js'; -export {default as inferredAdditionalNameList} from './inferredAdditionalNameList.js'; -export {default as inheritContributionListFromOriginalRelease} from './inheritContributionListFromOriginalRelease.js'; -export {default as inheritFromOriginalRelease} from './inheritFromOriginalRelease.js'; -export {default as sharedAdditionalNameList} from './sharedAdditionalNameList.js'; -export {default as trackReverseReferenceList} from './trackReverseReferenceList.js'; -export {default as withAlbum} from './withAlbum.js'; +export {default as inheritContributionListFromMainRelease} from './inheritContributionListFromMainRelease.js'; +export {default as inheritFromMainRelease} from './inheritFromMainRelease.js'; +export {default as withAllReleases} from './withAllReleases.js'; export {default as withAlwaysReferenceByDirectory} from './withAlwaysReferenceByDirectory.js'; export {default as withContainingTrackSection} from './withContainingTrackSection.js'; +export {default as withCoverArtistContribs} from './withCoverArtistContribs.js'; export {default as withDate} from './withDate.js'; +export {default as withDirectorySuffix} from './withDirectorySuffix.js'; export {default as withHasUniqueCoverArt} from './withHasUniqueCoverArt.js'; -export {default as withOriginalRelease} from './withOriginalRelease.js'; +export {default as withMainRelease} from './withMainRelease.js'; export {default as withOtherReleases} from './withOtherReleases.js'; export {default as withPropertyFromAlbum} from './withPropertyFromAlbum.js'; -export {default as withPropertyFromOriginalRelease} from './withPropertyFromOriginalRelease.js'; +export {default as withPropertyFromMainRelease} from './withPropertyFromMainRelease.js'; +export {default as withSuffixDirectoryFromAlbum} from './withSuffixDirectoryFromAlbum.js'; export {default as withTrackArtDate} from './withTrackArtDate.js'; +export {default as withTrackNumber} from './withTrackNumber.js'; diff --git a/src/data/composite/things/track/inferredAdditionalNameList.js b/src/data/composite/things/track/inferredAdditionalNameList.js deleted file mode 100644 index 58e8d2a1..00000000 --- a/src/data/composite/things/track/inferredAdditionalNameList.js +++ /dev/null @@ -1,67 +0,0 @@ -// Infers additional name entries from other releases that were titled -// differently; the corresponding releases are stored in eacn entry's "from" -// array, which will include multiple items, if more than one other release -// shares the same name differing from this one's. - -import {input, templateCompositeFrom} from '#composite'; -import {chunkByProperties} from '#sugar'; - -import {exitWithoutDependency} from '#composite/control-flow'; -import {withFilteredList, withPropertyFromList} from '#composite/data'; -import {withThingsSortedAlphabetically} from '#composite/wiki-data'; - -import withOtherReleases from './withOtherReleases.js'; - -export default templateCompositeFrom({ - annotation: `inferredAdditionalNameList`, - - compose: false, - - steps: () => [ - withOtherReleases(), - - exitWithoutDependency({ - dependency: '#otherReleases', - mode: input.value('empty'), - value: input.value([]), - }), - - withPropertyFromList({ - list: '#otherReleases', - property: input.value('name'), - }), - - { - dependencies: ['#otherReleases.name', 'name'], - compute: (continuation, { - ['#otherReleases.name']: releaseNames, - ['name']: ownName, - }) => continuation({ - ['#nameFilter']: - releaseNames.map(name => name !== ownName), - }), - }, - - withFilteredList({ - list: '#otherReleases', - filter: '#nameFilter', - }).outputs({ - '#filteredList': '#differentlyNamedReleases', - }), - - withThingsSortedAlphabetically({ - things: '#differentlyNamedReleases', - }).outputs({ - '#sortedThings': '#differentlyNamedReleases', - }), - - { - dependencies: ['#differentlyNamedReleases'], - compute: ({ - ['#differentlyNamedReleases']: releases, - }) => - chunkByProperties(releases, ['name']) - .map(({name, chunk}) => ({name, from: chunk})), - }, - ], -}); diff --git a/src/data/composite/things/track/inheritContributionListFromOriginalRelease.js b/src/data/composite/things/track/inheritContributionListFromMainRelease.js index f4ae3ddb..89252feb 100644 --- a/src/data/composite/things/track/inheritContributionListFromOriginalRelease.js +++ b/src/data/composite/things/track/inheritContributionListFromMainRelease.js @@ -1,5 +1,5 @@ -// Like inheritFromOriginalRelease, but tuned for contributions. -// Recontextualized contributions for this track. +// Like inheritFromMainRelease, but tuned for contributions. +// Recontextualizes contributions for this track. import {input, templateCompositeFrom} from '#composite'; @@ -9,36 +9,36 @@ import {withRecontextualizedContributionList, withRedatedContributionList} from '#composite/wiki-data'; import withDate from './withDate.js'; -import withPropertyFromOriginalRelease - from './withPropertyFromOriginalRelease.js'; +import withPropertyFromMainRelease + from './withPropertyFromMainRelease.js'; export default templateCompositeFrom({ - annotation: `inheritContributionListFromOriginalRelease`, + annotation: `inheritContributionListFromMainRelease`, steps: () => [ - withPropertyFromOriginalRelease({ + withPropertyFromMainRelease({ property: input.thisProperty(), notFoundValue: input.value([]), }), raiseOutputWithoutDependency({ - dependency: '#isRerelease', + dependency: '#isSecondaryRelease', mode: input.value('falsy'), }), withRecontextualizedContributionList({ - list: '#originalValue', + list: '#mainReleaseValue', }), withDate(), withRedatedContributionList({ - list: '#originalValue', + list: '#mainReleaseValue', date: '#date', }), exposeDependency({ - dependency: '#originalValue', + dependency: '#mainReleaseValue', }), ], }); diff --git a/src/data/composite/things/track/inheritFromOriginalRelease.js b/src/data/composite/things/track/inheritFromMainRelease.js index 38ab06be..b1cbb65e 100644 --- a/src/data/composite/things/track/inheritFromOriginalRelease.js +++ b/src/data/composite/things/track/inheritFromMainRelease.js @@ -1,9 +1,9 @@ // Early exits with the value for the same property as specified on the -// original release, if this track is a rerelease, and otherwise continues +// main release, if this track is a secondary release, and otherwise continues // without providing any further dependencies. // -// Like withOriginalRelease, this will early exit (with notFoundValue) if the -// original release is specified by reference and that reference doesn't +// Like withMainRelease, this will early exit (with notFoundValue) if the +// main release is specified by reference and that reference doesn't // resolve to anything. import {input, templateCompositeFrom} from '#composite'; @@ -11,11 +11,11 @@ import {input, templateCompositeFrom} from '#composite'; import {exposeDependency, raiseOutputWithoutDependency} from '#composite/control-flow'; -import withPropertyFromOriginalRelease - from './withPropertyFromOriginalRelease.js'; +import withPropertyFromMainRelease + from './withPropertyFromMainRelease.js'; export default templateCompositeFrom({ - annotation: `inheritFromOriginalRelease`, + annotation: `inheritFromMainRelease`, inputs: { notFoundValue: input({ @@ -24,18 +24,18 @@ export default templateCompositeFrom({ }, steps: () => [ - withPropertyFromOriginalRelease({ + withPropertyFromMainRelease({ property: input.thisProperty(), notFoundValue: input('notFoundValue'), }), raiseOutputWithoutDependency({ - dependency: '#isRerelease', + dependency: '#isSecondaryRelease', mode: input.value('falsy'), }), exposeDependency({ - dependency: '#originalValue', + dependency: '#mainReleaseValue', }), ], }); diff --git a/src/data/composite/things/track/sharedAdditionalNameList.js b/src/data/composite/things/track/sharedAdditionalNameList.js deleted file mode 100644 index 1806ec80..00000000 --- a/src/data/composite/things/track/sharedAdditionalNameList.js +++ /dev/null @@ -1,38 +0,0 @@ -// Compiles additional names directly provided by other releases. - -import {input, templateCompositeFrom} from '#composite'; - -import {exitWithoutDependency, exposeDependency} - from '#composite/control-flow'; -import {withFlattenedList, withPropertyFromList} from '#composite/data'; - -import withOtherReleases from './withOtherReleases.js'; - -export default templateCompositeFrom({ - annotation: `sharedAdditionalNameList`, - - compose: false, - - steps: () => [ - withOtherReleases(), - - exitWithoutDependency({ - dependency: '#otherReleases', - mode: input.value('empty'), - value: input.value([]), - }), - - withPropertyFromList({ - list: '#otherReleases', - property: input.value('additionalNames'), - }), - - withFlattenedList({ - list: '#otherReleases.additionalNames', - }), - - exposeDependency({ - dependency: '#flattenedList', - }), - ], -}); diff --git a/src/data/composite/things/track/trackAdditionalNameList.js b/src/data/composite/things/track/trackAdditionalNameList.js deleted file mode 100644 index 65a2263d..00000000 --- a/src/data/composite/things/track/trackAdditionalNameList.js +++ /dev/null @@ -1,38 +0,0 @@ -// Compiles additional names from various sources. - -import {input, templateCompositeFrom} from '#composite'; -import {isAdditionalNameList} from '#validators'; - -import withInferredAdditionalNames from './withInferredAdditionalNames.js'; -import withSharedAdditionalNames from './withSharedAdditionalNames.js'; - -export default templateCompositeFrom({ - annotation: `trackAdditionalNameList`, - - compose: false, - - update: {validate: isAdditionalNameList}, - - steps: () => [ - withInferredAdditionalNames(), - withSharedAdditionalNames(), - - { - dependencies: [ - '#inferredAdditionalNames', - '#sharedAdditionalNames', - input.updateValue(), - ], - - compute: ({ - ['#inferredAdditionalNames']: inferredAdditionalNames, - ['#sharedAdditionalNames']: sharedAdditionalNames, - [input.updateValue()]: providedAdditionalNames, - }) => [ - ...providedAdditionalNames ?? [], - ...sharedAdditionalNames, - ...inferredAdditionalNames, - ], - }, - ], -}); diff --git a/src/data/composite/things/track/trackReverseReferenceList.js b/src/data/composite/things/track/trackReverseReferenceList.js deleted file mode 100644 index 44940ae7..00000000 --- a/src/data/composite/things/track/trackReverseReferenceList.js +++ /dev/null @@ -1,38 +0,0 @@ -// Like a normal reverse reference list ("objects which reference this object -// under a specified property"), only excluding rereleases from the possible -// outputs. While it's useful to travel from a rerelease to the tracks it -// references, rereleases aren't generally relevant from the perspective of -// the tracks *being* referenced. Apart from hiding rereleases from lists on -// the site, it also excludes keeps them from relational data processing, such -// as on the "Tracks - by Times Referenced" listing page. - -import {input, templateCompositeFrom} from '#composite'; -import {withReverseReferenceList} from '#composite/wiki-data'; - -export default templateCompositeFrom({ - annotation: `trackReverseReferenceList`, - - compose: false, - - inputs: { - list: input({type: 'string'}), - }, - - steps: () => [ - withReverseReferenceList({ - data: 'trackData', - list: input('list'), - }), - - { - flags: {expose: true}, - expose: { - dependencies: ['#reverseReferenceList'], - compute: ({ - ['#reverseReferenceList']: reverseReferenceList, - }) => - reverseReferenceList.filter(track => !track.originalReleaseTrack), - }, - }, - ], -}); diff --git a/src/data/composite/things/track/withAlbum.js b/src/data/composite/things/track/withAlbum.js deleted file mode 100644 index 03b840d4..00000000 --- a/src/data/composite/things/track/withAlbum.js +++ /dev/null @@ -1,22 +0,0 @@ -// Gets the track's album. This will early exit if albumData is missing. -// If there's no album whose list of tracks includes this track, the output -// dependency will be null. - -import {input, templateCompositeFrom} from '#composite'; - -import {withUniqueReferencingThing} from '#composite/wiki-data'; - -export default templateCompositeFrom({ - annotation: `withAlbum`, - - outputs: ['#album'], - - steps: () => [ - withUniqueReferencingThing({ - data: 'albumData', - list: input.value('tracks'), - }).outputs({ - ['#uniqueReferencingThing']: '#album', - }), - ], -}); diff --git a/src/data/composite/things/track/withAllReleases.js b/src/data/composite/things/track/withAllReleases.js new file mode 100644 index 00000000..891db102 --- /dev/null +++ b/src/data/composite/things/track/withAllReleases.js @@ -0,0 +1,46 @@ +// Gets all releases of the current track. All items of the outputs are +// distinct Track objects; one track is the main release; all else are +// secondary releases of that main release; and one item, which may be +// the main release or one of the secondary releases, is the current +// track. The results are sorted by date, and it is possible that the +// main release is not actually the earliest/first. + +import {input, templateCompositeFrom} from '#composite'; +import {sortByDate} from '#sort'; + +import {withPropertyFromObject} from '#composite/data'; + +import withMainRelease from './withMainRelease.js'; + +export default templateCompositeFrom({ + annotation: `withAllReleases`, + + outputs: ['#allReleases'], + + steps: () => [ + withMainRelease({ + selfIfMain: input.value(true), + notFoundValue: input.value([]), + }), + + // We don't talk about bruno no no + // Yes, this can perform a normal access equivalent to + // `this.secondaryReleases` from within a data composition. + // Oooooooooooooooooooooooooooooooooooooooooooooooo + withPropertyFromObject({ + object: '#mainRelease', + property: input.value('secondaryReleases'), + }), + + { + dependencies: ['#mainRelease', '#mainRelease.secondaryReleases'], + compute: (continuation, { + ['#mainRelease']: mainRelease, + ['#mainRelease.secondaryReleases']: secondaryReleases, + }) => continuation({ + ['#allReleases']: + sortByDate([mainRelease, ...secondaryReleases]), + }), + }, + ], +}); diff --git a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js index e01720b4..87edf21e 100644 --- a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js +++ b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js @@ -16,6 +16,8 @@ import { exposeUpdateValueOrContinue, } from '#composite/control-flow'; +import withPropertyFromAlbum from './withPropertyFromAlbum.js'; + export default templateCompositeFrom({ annotation: `withAlwaysReferenceByDirectory`, @@ -26,19 +28,7 @@ export default templateCompositeFrom({ validate: input.value(isBoolean), }), - // withAlwaysReferenceByDirectory is sort of a fragile area - we can't - // find the track's album the normal way because albums' track lists - // recurse back into alwaysReferenceByDirectory! - withResolvedReference({ - ref: 'dataSourceAlbum', - data: 'albumData', - find: input.value(find.album), - }).outputs({ - '#resolvedReference': '#album', - }), - - withPropertyFromObject({ - object: '#album', + withPropertyFromAlbum({ property: input.value('alwaysReferenceTracksByDirectory'), }), @@ -51,7 +41,7 @@ export default templateCompositeFrom({ // Remaining code is for defaulting to true if this track is a rerelease of // another with the same name, so everything further depends on access to - // trackData as well as originalReleaseTrack. + // trackData as well as mainReleaseTrack. exitWithoutDependency({ dependency: 'trackData', @@ -60,45 +50,46 @@ export default templateCompositeFrom({ }), exitWithoutDependency({ - dependency: 'originalReleaseTrack', + dependency: 'mainReleaseTrack', value: input.value(false), }), - // It's necessary to use the custom trackOriginalReleasesOnly find function + // It's necessary to use the custom trackMainReleasesOnly find function // here, so as to avoid recursion issues - the find.track() function depends // on accessing each track's alwaysReferenceByDirectory, which means it'll // hit *this track* - and thus this step - and end up recursing infinitely. - // By definition, find.trackOriginalReleasesOnly excludes tracks which have - // an originalReleaseTrack update value set, which means even though it does + // By definition, find.trackMainReleasesOnly excludes tracks which have + // an mainReleaseTrack update value set, which means even though it does // still access each of tracks' `alwaysReferenceByDirectory` property, it // won't access that of *this* track - it will never proceed past the // `exitWithoutDependency` step directly above, so there's no opportunity // for recursion. withResolvedReference({ - ref: 'originalReleaseTrack', + ref: 'mainReleaseTrack', data: 'trackData', - find: input.value(find.trackOriginalReleasesOnly), + find: input.value(find.trackMainReleasesOnly), }).outputs({ - '#resolvedReference': '#originalRelease', + '#resolvedReference': '#mainRelease', }), exitWithoutDependency({ - dependency: '#originalRelease', + dependency: '#mainRelease', value: input.value(false), }), withPropertyFromObject({ - object: '#originalRelease', + object: '#mainRelease', property: input.value('name'), }), { - dependencies: ['name', '#originalRelease.name'], + dependencies: ['name', '#mainRelease.name'], compute: (continuation, { name, - ['#originalRelease.name']: originalName, + ['#mainRelease.name']: mainReleaseName, }) => continuation({ - ['#alwaysReferenceByDirectory']: name === originalName, + ['#alwaysReferenceByDirectory']: + name === mainReleaseName, }), }, ], diff --git a/src/data/composite/things/track/withContainingTrackSection.js b/src/data/composite/things/track/withContainingTrackSection.js index 2c42709b..3d4d081e 100644 --- a/src/data/composite/things/track/withContainingTrackSection.js +++ b/src/data/composite/things/track/withContainingTrackSection.js @@ -1,11 +1,9 @@ // Gets the track section containing this track from its album's track list. -import {input, templateCompositeFrom} from '#composite'; -import {is} from '#validators'; +import {templateCompositeFrom} from '#composite'; -import {raiseOutputWithoutDependency} from '#composite/control-flow'; - -import withPropertyFromAlbum from './withPropertyFromAlbum.js'; +import {withUniqueReferencingThing} from '#composite/wiki-data'; +import {soupyReverse} from '#composite/wiki-properties'; export default templateCompositeFrom({ annotation: `withContainingTrackSection`, @@ -13,29 +11,10 @@ export default templateCompositeFrom({ outputs: ['#trackSection'], steps: () => [ - withPropertyFromAlbum({ - property: input.value('trackSections'), - }), - - raiseOutputWithoutDependency({ - dependency: '#album.trackSections', - output: input.value({'#trackSection': null}), + withUniqueReferencingThing({ + reverse: soupyReverse.input('trackSectionsWhichInclude'), + }).outputs({ + ['#uniqueReferencingThing']: '#trackSection', }), - - { - dependencies: [ - input.myself(), - '#album.trackSections', - ], - - compute: (continuation, { - [input.myself()]: track, - ['#album.trackSections']: trackSections, - }) => continuation({ - ['#trackSection']: - trackSections.find(({tracks}) => tracks.includes(track)) - ?? null, - }), - }, ], }); diff --git a/src/data/composite/things/track/withCoverArtistContribs.js b/src/data/composite/things/track/withCoverArtistContribs.js new file mode 100644 index 00000000..9057cfeb --- /dev/null +++ b/src/data/composite/things/track/withCoverArtistContribs.js @@ -0,0 +1,73 @@ +import {input, templateCompositeFrom} from '#composite'; +import {isContributionList} from '#validators'; + +import {exposeDependencyOrContinue} from '#composite/control-flow'; + +import { + withRecontextualizedContributionList, + withRedatedContributionList, + withResolvedContribs, +} from '#composite/wiki-data'; + +import exitWithoutUniqueCoverArt from './exitWithoutUniqueCoverArt.js'; +import withPropertyFromAlbum from './withPropertyFromAlbum.js'; +import withTrackArtDate from './withTrackArtDate.js'; + +export default templateCompositeFrom({ + annotation: `withCoverArtistContribs`, + + inputs: { + from: input({ + defaultDependency: 'coverArtistContribs', + validate: isContributionList, + acceptsNull: true, + }), + }, + + outputs: ['#coverArtistContribs'], + + steps: () => [ + exitWithoutUniqueCoverArt({ + value: input.value([]), + }), + + withTrackArtDate(), + + withResolvedContribs({ + from: input('from'), + thingProperty: input.value('coverArtistContribs'), + artistProperty: input.value('trackCoverArtistContributions'), + date: '#trackArtDate', + }).outputs({ + '#resolvedContribs': '#coverArtistContribs', + }), + + exposeDependencyOrContinue({ + dependency: '#coverArtistContribs', + mode: input.value('empty'), + }), + + withPropertyFromAlbum({ + property: input.value('trackCoverArtistContribs'), + }), + + withRecontextualizedContributionList({ + list: '#album.trackCoverArtistContribs', + artistProperty: input.value('trackCoverArtistContributions'), + }), + + withRedatedContributionList({ + list: '#album.trackCoverArtistContribs', + date: '#trackArtDate', + }), + + { + dependencies: ['#album.trackCoverArtistContribs'], + compute: (continuation, { + ['#album.trackCoverArtistContribs']: coverArtistContribs, + }) => continuation({ + ['#coverArtistContribs']: coverArtistContribs, + }), + }, + ], +}); diff --git a/src/data/composite/things/track/withDirectorySuffix.js b/src/data/composite/things/track/withDirectorySuffix.js new file mode 100644 index 00000000..c063e158 --- /dev/null +++ b/src/data/composite/things/track/withDirectorySuffix.js @@ -0,0 +1,36 @@ +import {input, templateCompositeFrom} from '#composite'; + +import {raiseOutputWithoutDependency} from '#composite/control-flow'; + +import withPropertyFromAlbum from './withPropertyFromAlbum.js'; +import withSuffixDirectoryFromAlbum from './withSuffixDirectoryFromAlbum.js'; + +export default templateCompositeFrom({ + annotation: `withDirectorySuffix`, + + outputs: ['#directorySuffix'], + + steps: () => [ + withSuffixDirectoryFromAlbum(), + + raiseOutputWithoutDependency({ + dependency: '#suffixDirectoryFromAlbum', + mode: input.value('falsy'), + output: input.value({['#directorySuffix']: null}), + }), + + withPropertyFromAlbum({ + property: input.value('directorySuffix'), + }), + + { + dependencies: ['#album.directorySuffix'], + compute: (continuation, { + ['#album.directorySuffix']: directorySuffix, + }) => continuation({ + ['#directorySuffix']: + directorySuffix, + }), + }, + ], +}); diff --git a/src/data/composite/things/track/withHasUniqueCoverArt.js b/src/data/composite/things/track/withHasUniqueCoverArt.js index f7e65f25..85d3b92a 100644 --- a/src/data/composite/things/track/withHasUniqueCoverArt.js +++ b/src/data/composite/things/track/withHasUniqueCoverArt.js @@ -5,11 +5,18 @@ // or a placeholder. (This property is named hasUniqueCoverArt instead of // the usual hasCoverArt to emphasize that it does not inherit from the // album.) +// +// withHasUniqueCoverArt is based only around the presence of *specified* +// cover artist contributions, not whether the references to artists on those +// contributions actually resolve to anything. It completely evades interacting +// with find/replace. import {input, templateCompositeFrom} from '#composite'; -import {empty} from '#sugar'; -import {withResolvedContribs} from '#composite/wiki-data'; +import {raiseOutputWithoutDependency, withResultOfAvailabilityCheck} + from '#composite/control-flow'; +import {fillMissingListItems, withFlattenedList, withPropertyFromList} + from '#composite/data'; import withPropertyFromAlbum from './withPropertyFromAlbum.js'; @@ -29,36 +36,73 @@ export default templateCompositeFrom({ : continuation()), }, - withResolvedContribs({ + withResultOfAvailabilityCheck({ from: 'coverArtistContribs', - date: input.value(null), + mode: input.value('empty'), }), { - dependencies: ['#resolvedContribs'], + dependencies: ['#availability'], compute: (continuation, { - ['#resolvedContribs']: contribsFromTrack, + ['#availability']: availability, }) => - (empty(contribsFromTrack) - ? continuation() - : continuation.raiseOutput({ + (availability + ? continuation.raiseOutput({ ['#hasUniqueCoverArt']: true, - })), + }) + : continuation()), }, withPropertyFromAlbum({ property: input.value('trackCoverArtistContribs'), + internal: input.value(true), + }), + + withResultOfAvailabilityCheck({ + from: '#album.trackCoverArtistContribs', + mode: input.value('empty'), }), { - dependencies: ['#album.trackCoverArtistContribs'], + dependencies: ['#availability'], compute: (continuation, { - ['#album.trackCoverArtistContribs']: contribsFromAlbum, + ['#availability']: availability, }) => - continuation.raiseOutput({ - ['#hasUniqueCoverArt']: - !empty(contribsFromAlbum), - }), + (availability + ? continuation.raiseOutput({ + ['#hasUniqueCoverArt']: true, + }) + : continuation()), }, + + raiseOutputWithoutDependency({ + dependency: 'trackArtworks', + mode: input.value('empty'), + output: input.value({'#hasUniqueCoverArt': false}), + }), + + withPropertyFromList({ + list: 'trackArtworks', + property: input.value('artistContribs'), + internal: input.value(true), + }), + + // Since we're getting the update value for each artwork's artistContribs, + // it may not be set at all, and in that case won't be exposing as []. + fillMissingListItems({ + list: '#trackArtworks.artistContribs', + fill: input.value([]), + }), + + withFlattenedList({ + list: '#trackArtworks.artistContribs', + }), + + withResultOfAvailabilityCheck({ + from: '#flattenedList', + mode: input.value('empty'), + }).outputs({ + '#availability': '#hasUniqueCoverArt', + }), ], }); diff --git a/src/data/composite/things/track/withOriginalRelease.js b/src/data/composite/things/track/withMainRelease.js index c7f49657..3a91edae 100644 --- a/src/data/composite/things/track/withOriginalRelease.js +++ b/src/data/composite/things/track/withMainRelease.js @@ -1,62 +1,54 @@ -// Just includes the original release of this track as a dependency. -// If this track isn't a rerelease, then it'll provide null, unless the -// {selfIfOriginal} option is set, in which case it'll provide this track -// itself. This will early exit (with notFoundValue) if the original release +// Just includes the main release of this track as a dependency. +// If this track isn't a secondary release, then it'll provide null, unless +// the {selfIfMain} option is set, in which case it'll provide this track +// itself. This will early exit (with notFoundValue) if the main release // is specified by reference and that reference doesn't resolve to anything. import {input, templateCompositeFrom} from '#composite'; -import find from '#find'; -import {validateWikiData} from '#validators'; import {exitWithoutDependency, withResultOfAvailabilityCheck} from '#composite/control-flow'; import {withResolvedReference} from '#composite/wiki-data'; +import {soupyFind} from '#composite/wiki-properties'; export default templateCompositeFrom({ - annotation: `withOriginalRelease`, + annotation: `withMainRelease`, inputs: { - selfIfOriginal: input({type: 'boolean', defaultValue: false}), - - data: input({ - validate: validateWikiData({referenceType: 'track'}), - defaultDependency: 'trackData', - }), - + selfIfMain: input({type: 'boolean', defaultValue: false}), notFoundValue: input({defaultValue: null}), }, - outputs: ['#originalRelease'], + outputs: ['#mainRelease'], steps: () => [ withResultOfAvailabilityCheck({ - from: 'originalReleaseTrack', + from: 'mainReleaseTrack', }), { dependencies: [ input.myself(), - input('selfIfOriginal'), + input('selfIfMain'), '#availability', ], compute: (continuation, { [input.myself()]: track, - [input('selfIfOriginal')]: selfIfOriginal, + [input('selfIfMain')]: selfIfMain, '#availability': availability, }) => (availability ? continuation() : continuation.raiseOutput({ - ['#originalRelease']: - (selfIfOriginal ? track : null), + ['#mainRelease']: + (selfIfMain ? track : null), })), }, withResolvedReference({ - ref: 'originalReleaseTrack', - data: input('data'), - find: input.value(find.track), + ref: 'mainReleaseTrack', + find: soupyFind.input('track'), }), exitWithoutDependency({ @@ -71,7 +63,7 @@ export default templateCompositeFrom({ ['#resolvedReference']: resolvedReference, }) => continuation({ - ['#originalRelease']: resolvedReference, + ['#mainRelease']: resolvedReference, }), }, ], diff --git a/src/data/composite/things/track/withOtherReleases.js b/src/data/composite/things/track/withOtherReleases.js index f8c1c3f0..bb3e8983 100644 --- a/src/data/composite/things/track/withOtherReleases.js +++ b/src/data/composite/things/track/withOtherReleases.js @@ -1,8 +1,9 @@ -import {input, templateCompositeFrom} from '#composite'; +// Gets all releases of the current track *except* this track itself; +// in other words, all other releases of the current track. -import {exitWithoutDependency} from '#composite/control-flow'; +import {input, templateCompositeFrom} from '#composite'; -import withOriginalRelease from './withOriginalRelease.js'; +import withAllReleases from './withAllReleases.js'; export default templateCompositeFrom({ annotation: `withOtherReleases`, @@ -10,31 +11,16 @@ export default templateCompositeFrom({ outputs: ['#otherReleases'], steps: () => [ - exitWithoutDependency({ - dependency: 'trackData', - mode: input.value('empty'), - }), - - withOriginalRelease({ - selfIfOriginal: input.value(true), - notFoundValue: input.value([]), - }), + withAllReleases(), { - dependencies: [input.myself(), '#originalRelease', 'trackData'], + dependencies: [input.myself(), '#allReleases'], compute: (continuation, { [input.myself()]: thisTrack, - ['#originalRelease']: originalRelease, - trackData, + ['#allReleases']: allReleases, }) => continuation({ ['#otherReleases']: - (originalRelease === thisTrack - ? [] - : [originalRelease]) - .concat(trackData.filter(track => - track !== originalRelease && - track !== thisTrack && - track.originalReleaseTrack === originalRelease)), + allReleases.filter(track => track !== thisTrack), }), }, ], diff --git a/src/data/composite/things/track/withPropertyFromAlbum.js b/src/data/composite/things/track/withPropertyFromAlbum.js index d41390fa..a203c2e7 100644 --- a/src/data/composite/things/track/withPropertyFromAlbum.js +++ b/src/data/composite/things/track/withPropertyFromAlbum.js @@ -2,17 +2,15 @@ // property name prefixed with '#album.' (by default). import {input, templateCompositeFrom} from '#composite'; -import {is} from '#validators'; import {withPropertyFromObject} from '#composite/data'; -import withAlbum from './withAlbum.js'; - export default templateCompositeFrom({ annotation: `withPropertyFromAlbum`, inputs: { property: input.staticValue({type: 'string'}), + internal: input({type: 'boolean', defaultValue: false}), }, outputs: ({ @@ -20,11 +18,21 @@ export default templateCompositeFrom({ }) => ['#album.' + property], steps: () => [ - withAlbum(), + // XXX: This is a ridiculous hack considering `defaultValue` above. + // If we were certain what was up, we'd just get around to fixing it LOL + { + dependencies: [input('internal')], + compute: (continuation, { + [input('internal')]: internal, + }) => continuation({ + ['#internal']: internal ?? false, + }), + }, withPropertyFromObject({ - object: '#album', + object: 'album', property: input('property'), + internal: '#internal', }), { diff --git a/src/data/composite/things/track/withPropertyFromOriginalRelease.js b/src/data/composite/things/track/withPropertyFromMainRelease.js index fd37f6de..393a4c63 100644 --- a/src/data/composite/things/track/withPropertyFromOriginalRelease.js +++ b/src/data/composite/things/track/withPropertyFromMainRelease.js @@ -1,8 +1,8 @@ -// Provides a value inherited from the original release, if applicable, and a -// flag indicating if this track is a rerelase or not. +// Provides a value inherited from the main release, if applicable, and a +// flag indicating if this track is a secondary release or not. // -// Like withOriginalRelease, this will early exit (with notFoundValue) if the -// original release is specified by reference and that reference doesn't +// Like withMainRelease, this will early exit (with notFoundValue) if the +// main release is specified by reference and that reference doesn't // resolve to anything. import {input, templateCompositeFrom} from '#composite'; @@ -10,10 +10,10 @@ import {input, templateCompositeFrom} from '#composite'; import {withResultOfAvailabilityCheck} from '#composite/control-flow'; import {withPropertyFromObject} from '#composite/data'; -import withOriginalRelease from './withOriginalRelease.js'; +import withMainRelease from './withMainRelease.js'; export default templateCompositeFrom({ - annotation: `inheritFromOriginalRelease`, + annotation: `inheritFromMainRelease`, inputs: { property: input({type: 'string'}), @@ -26,18 +26,18 @@ export default templateCompositeFrom({ outputs: ({ [input.staticValue('property')]: property, }) => - ['#isRerelease'].concat( + ['#isSecondaryRelease'].concat( (property - ? ['#original.' + property] - : ['#originalValue'])), + ? ['#mainRelease.' + property] + : ['#mainReleaseValue'])), steps: () => [ - withOriginalRelease({ + withMainRelease({ notFoundValue: input('notFoundValue'), }), withResultOfAvailabilityCheck({ - from: '#originalRelease', + from: '#mainRelease', }), { @@ -54,14 +54,14 @@ export default templateCompositeFrom({ ? continuation() : continuation.raiseOutput( Object.assign( - {'#isRerelease': false}, + {'#isSecondaryRelease': false}, (property - ? {['#original.' + property]: null} - : {'#originalValue': null})))), + ? {['#mainRelease.' + property]: null} + : {'#mainReleaseValue': null})))), }, withPropertyFromObject({ - object: '#originalRelease', + object: '#mainRelease', property: input('property'), }), @@ -77,10 +77,10 @@ export default templateCompositeFrom({ }) => continuation.raiseOutput( Object.assign( - {'#isRerelease': true}, + {'#isSecondaryRelease': true}, (property - ? {['#original.' + property]: value} - : {'#originalValue': value}))), + ? {['#mainRelease.' + property]: value} + : {'#mainReleaseValue': value}))), }, ], }); diff --git a/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js b/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js new file mode 100644 index 00000000..7159a3f4 --- /dev/null +++ b/src/data/composite/things/track/withSuffixDirectoryFromAlbum.js @@ -0,0 +1,53 @@ +import {input, templateCompositeFrom} from '#composite'; + +import {withResultOfAvailabilityCheck} from '#composite/control-flow'; + +import withPropertyFromAlbum from './withPropertyFromAlbum.js'; + +export default templateCompositeFrom({ + annotation: `withSuffixDirectoryFromAlbum`, + + inputs: { + flagValue: input({ + defaultDependency: 'suffixDirectoryFromAlbum', + acceptsNull: true, + }), + }, + + outputs: ['#suffixDirectoryFromAlbum'], + + steps: () => [ + withResultOfAvailabilityCheck({ + from: 'suffixDirectoryFromAlbum', + }), + + { + dependencies: [ + '#availability', + 'suffixDirectoryFromAlbum' + ], + + compute: (continuation, { + ['#availability']: availability, + ['suffixDirectoryFromAlbum']: flagValue, + }) => + (availability + ? continuation.raiseOutput({['#suffixDirectoryFromAlbum']: flagValue}) + : continuation()), + }, + + withPropertyFromAlbum({ + property: input.value('suffixTrackDirectories'), + }), + + { + dependencies: ['#album.suffixTrackDirectories'], + compute: (continuation, { + ['#album.suffixTrackDirectories']: suffixTrackDirectories, + }) => continuation({ + ['#suffixDirectoryFromAlbum']: + suffixTrackDirectories, + }), + }, + ], +}); diff --git a/src/data/composite/things/track/withTrackArtDate.js b/src/data/composite/things/track/withTrackArtDate.js index e2c4d8bc..9b7b61c7 100644 --- a/src/data/composite/things/track/withTrackArtDate.js +++ b/src/data/composite/things/track/withTrackArtDate.js @@ -1,11 +1,3 @@ -// Gets the date of cover art release. This represents only the track's own -// unique cover artwork, if any. -// -// If the 'fallback' option is false (the default), this will only output -// the track's own coverArtDate or its album's trackArtDate. If 'fallback' -// is set, and neither of these is available, it'll output the track's own -// date instead. - import {input, templateCompositeFrom} from '#composite'; import {isDate} from '#validators'; @@ -24,11 +16,6 @@ export default templateCompositeFrom({ defaultDependency: 'coverArtDate', acceptsNull: true, }), - - fallback: input({ - type: 'boolean', - defaultValue: false, - }), }, outputs: ['#trackArtDate'], @@ -57,20 +44,13 @@ export default templateCompositeFrom({ }), { - dependencies: [ - '#album.trackArtDate', - input('fallback'), - ], - + dependencies: ['#album.trackArtDate'], compute: (continuation, { ['#album.trackArtDate']: albumTrackArtDate, - [input('fallback')]: fallback, }) => (albumTrackArtDate ? continuation.raiseOutput({'#trackArtDate': albumTrackArtDate}) - : fallback - ? continuation() - : continuation.raiseOutput({'#trackArtDate': null})), + : continuation()), }, withDate().outputs({ diff --git a/src/data/composite/things/track/withTrackNumber.js b/src/data/composite/things/track/withTrackNumber.js new file mode 100644 index 00000000..61428e8c --- /dev/null +++ b/src/data/composite/things/track/withTrackNumber.js @@ -0,0 +1,50 @@ +import {input, templateCompositeFrom} from '#composite'; + +import {raiseOutputWithoutDependency} from '#composite/control-flow'; +import {withIndexInList, withPropertiesFromObject} from '#composite/data'; + +import withContainingTrackSection from './withContainingTrackSection.js'; + +export default templateCompositeFrom({ + annotation: `withTrackNumber`, + + outputs: ['#trackNumber'], + + steps: () => [ + withContainingTrackSection(), + + // Zero is the fallback, not one, but in most albums the first track + // (and its intended output by this composition) will be one. + raiseOutputWithoutDependency({ + dependency: '#trackSection', + output: input.value({'#trackNumber': 0}), + }), + + withPropertiesFromObject({ + object: '#trackSection', + properties: input.value(['tracks', 'startCountingFrom']), + }), + + withIndexInList({ + list: '#trackSection.tracks', + item: input.myself(), + }), + + raiseOutputWithoutDependency({ + dependency: '#index', + output: input.value({'#trackNumber': 0}), + }), + + { + dependencies: ['#trackSection.startCountingFrom', '#index'], + compute: (continuation, { + ['#trackSection.startCountingFrom']: startCountingFrom, + ['#index']: index, + }) => continuation({ + ['#trackNumber']: + startCountingFrom + + index, + }), + }, + ], +}); |