« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/things/contribution.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/data/things/contribution.js')
-rw-r--r--src/data/things/contribution.js239
1 files changed, 120 insertions, 119 deletions
diff --git a/src/data/things/contribution.js b/src/data/things/contribution.js
index c92fafb4..393a60b4 100644
--- a/src/data/things/contribution.js
+++ b/src/data/things/contribution.js
@@ -2,13 +2,21 @@ import {inspect} from 'node:util';
 
 import CacheableObject from '#cacheable-object';
 import {colors} from '#cli';
-import {input} from '#composite';
+import {input, V} from '#composite';
 import {empty} from '#sugar';
 import Thing from '#thing';
-import {isStringNonEmpty, isThing, validateReference} from '#validators';
+import {isBoolean, isStringNonEmpty, isThing} from '#validators';
 
-import {exitWithoutDependency, exposeDependency} from '#composite/control-flow';
-import {flag, simpleDate, soupyFind} from '#composite/wiki-properties';
+import {simpleDate, singleReference, soupyFind}
+  from '#composite/wiki-properties';
+
+import {
+  exitWithoutDependency,
+  exposeConstant,
+  exposeDependency,
+  exposeDependencyOrContinue,
+  exposeUpdateValueOrContinue,
+} from '#composite/control-flow';
 
 import {
   withFilteredList,
@@ -19,12 +27,8 @@ import {
 
 import {
   inheritFromContributionPresets,
-  thingPropertyMatches,
-  thingReferenceTypeMatches,
   withContainingReverseContributionList,
-  withContributionArtist,
   withContributionContext,
-  withMatchingContributionPresets,
 } from '#composite/things/contribution';
 
 export class Contribution extends Thing {
@@ -48,17 +52,9 @@ export class Contribution extends Thing {
 
     date: simpleDate(),
 
-    artist: [
-      withContributionArtist({
-        ref: input.updateValue({
-          validate: validateReference('artist'),
-        }),
-      }),
-
-      exposeDependency({
-        dependency: '#artist',
-      }),
-    ],
+    artist: singleReference({
+      find: soupyFind.input('artist'),
+    }),
 
     annotation: {
       flags: {update: true, expose: true},
@@ -66,19 +62,55 @@ export class Contribution extends Thing {
     },
 
     countInContributionTotals: [
-      inheritFromContributionPresets({
-        property: input.thisProperty(),
+      inheritFromContributionPresets(),
+
+      exposeUpdateValueOrContinue({
+        validate: input.value(isBoolean),
       }),
 
-      flag(true),
+      {
+        dependencies: ['thing', input.myself()],
+        compute: (continuation, {
+          ['thing']: thing,
+          [input.myself()]: contribution,
+        }) =>
+          (thing.countOwnContributionInContributionTotals?.(contribution)
+            ? true
+         : thing.countOwnContributionInContributionTotals
+            ? false
+            : continuation()),
+      },
+
+      exposeConstant(V(true)),
     ],
 
     countInDurationTotals: [
-      inheritFromContributionPresets({
-        property: input.thisProperty(),
+      inheritFromContributionPresets(),
+
+      exposeUpdateValueOrContinue({
+        validate: input.value(isBoolean),
       }),
 
-      flag(true),
+      withPropertyFromObject('thing', V('duration')),
+      exitWithoutDependency('#thing.duration', {
+        value: input.value(false),
+        mode: input.value('falsy'),
+      }),
+
+      {
+        dependencies: ['thing', input.myself()],
+        compute: (continuation, {
+          ['thing']: thing,
+          [input.myself()]: contribution,
+        }) =>
+          (thing.countOwnContributionInDurationTotals?.(contribution)
+            ? true
+         : thing.countOwnContributionInDurationTotals
+            ? false
+            : continuation()),
+      },
+
+      exposeConstant(V(true)),
     ],
 
     // Update only
@@ -87,6 +119,8 @@ export class Contribution extends Thing {
 
     // Expose only
 
+    isContribution: exposeConstant(V(true)),
+
     context: [
       withContributionContext(),
 
@@ -107,11 +141,43 @@ export class Contribution extends Thing {
     ],
 
     matchingPresets: [
-      withMatchingContributionPresets(),
-
-      exposeDependency({
-        dependency: '#matchingContributionPresets',
+      withPropertyFromObject('thing', {
+        property: input.value('wikiInfo'),
+        internal: input.value(true),
       }),
+
+      exitWithoutDependency('#thing.wikiInfo', V([])),
+
+      withPropertyFromObject('#thing.wikiInfo', V('contributionPresets'))
+        .outputs({'#thing.wikiInfo.contributionPresets': '#contributionPresets'}),
+
+      exitWithoutDependency('#contributionPresets', V([]), V('empty')),
+
+      withContributionContext(),
+
+      // TODO: implementing this with compositional filters would be fun
+      {
+        dependencies: [
+          '#contributionPresets',
+          '#contributionTarget',
+          '#contributionProperty',
+          'annotation',
+        ],
+
+        compute: ({
+          ['#contributionPresets']: presets,
+          ['#contributionTarget']: target,
+          ['#contributionProperty']: property,
+          ['annotation']: annotation,
+        }) =>
+          presets.filter(preset =>
+            preset.context[0] === target &&
+            preset.context.slice(1).includes(property) &&
+            // For now, only match if the annotation is a complete match.
+            // Partial matches (e.g. because the contribution includes "two"
+            // annotations, separated by commas) don't count.
+            preset.annotation === annotation),
+      },
     ],
 
     // All the contributions from the list which includes this contribution.
@@ -119,27 +185,13 @@ export class Contribution extends Thing {
     // artist, but also this very contribution. It doesn't mix contributions
     // exposed on different properties.
     associatedContributions: [
-      exitWithoutDependency({
-        dependency: 'thing',
-        value: input.value([]),
-      }),
+      exitWithoutDependency('thing', V([])),
+      exitWithoutDependency('thingProperty', V([])),
 
-      exitWithoutDependency({
-        dependency: 'thingProperty',
-        value: input.value([]),
-      }),
+      withPropertyFromObject('thing', 'thingProperty')
+        .outputs({'#value': '#contributions'}),
 
-      withPropertyFromObject({
-        object: 'thing',
-        property: 'thingProperty',
-      }).outputs({
-        '#value': '#contributions',
-      }),
-
-      withPropertyFromList({
-        list: '#contributions',
-        property: input.value('annotation'),
-      }),
+      withPropertyFromList('#contributions', V('annotation')),
 
       {
         dependencies: ['#contributions.annotation', 'annotation'],
@@ -155,88 +207,37 @@ export class Contribution extends Thing {
         }),
       },
 
-      withFilteredList({
-        list: '#contributions',
-        filter: '#likeContributionsFilter',
-      }).outputs({
-        '#filteredList': '#contributions',
-      }),
+      withFilteredList('#contributions', '#likeContributionsFilter')
+        .outputs({'#filteredList': '#contributions'}),
 
-      exposeDependency({
-        dependency: '#contributions',
-      }),
+      exposeDependency('#contributions'),
     ],
 
-    isArtistContribution: thingPropertyMatches({
-      value: input.value('artistContribs'),
-    }),
-
-    isContributorContribution: thingPropertyMatches({
-      value: input.value('contributorContribs'),
-    }),
-
-    isCoverArtistContribution: thingPropertyMatches({
-      value: input.value('coverArtistContribs'),
-    }),
-
-    isBannerArtistContribution: thingPropertyMatches({
-      value: input.value('bannerArtistContribs'),
-    }),
-
-    isWallpaperArtistContribution: thingPropertyMatches({
-      value: input.value('wallpaperArtistContribs'),
-    }),
-
-    isForTrack: thingReferenceTypeMatches({
-      value: input.value('track'),
-    }),
-
-    isForAlbum: thingReferenceTypeMatches({
-      value: input.value('album'),
-    }),
-
-    isForFlash: thingReferenceTypeMatches({
-      value: input.value('flash'),
-    }),
-
     previousBySameArtist: [
-      withContainingReverseContributionList().outputs({
-        '#containingReverseContributionList': '#list',
-      }),
-
-      exitWithoutDependency({
-        dependency: '#list',
-      }),
+      withContainingReverseContributionList()
+        .outputs({'#containingReverseContributionList': '#list'}),
 
-      withNearbyItemFromList({
-        list: '#list',
-        item: input.myself(),
-        offset: input.value(-1),
-      }),
+      exitWithoutDependency('#list'),
 
-      exposeDependency({
-        dependency: '#nearbyItem',
-      }),
+      withNearbyItemFromList('#list', input.myself(), V(-1)),
+      exposeDependency('#nearbyItem'),
     ],
 
     nextBySameArtist: [
-      withContainingReverseContributionList().outputs({
-        '#containingReverseContributionList': '#list',
-      }),
+      withContainingReverseContributionList()
+        .outputs({'#containingReverseContributionList': '#list'}),
 
-      exitWithoutDependency({
-        dependency: '#list',
-      }),
+      exitWithoutDependency('#list'),
 
-      withNearbyItemFromList({
-        list: '#list',
-        item: input.myself(),
-        offset: input.value(+1),
-      }),
+      withNearbyItemFromList('#list', input.myself(), V(+1)),
+      exposeDependency('#nearbyItem'),
+    ],
 
-      exposeDependency({
-        dependency: '#nearbyItem',
-      }),
+    groups: [
+      withPropertyFromObject('thing', V('groups')),
+      exposeDependencyOrContinue('#thing.groups'),
+
+      exposeConstant(V([])),
     ],
   });
 
@@ -259,7 +260,7 @@ export class Contribution extends Thing {
       let artist;
       try {
         artist = this.artist;
-      } catch (_error) {
+      } catch {
         // Computing artist might crash for any reason - don't distract from
         // other errors as a result of inspecting this contribution.
       }