« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/generateArtistGroupContributionsInfo.js124
-rw-r--r--src/content/dependencies/generateArtistInfoPage.js132
2 files changed, 154 insertions, 102 deletions
diff --git a/src/content/dependencies/generateArtistGroupContributionsInfo.js b/src/content/dependencies/generateArtistGroupContributionsInfo.js
new file mode 100644
index 00000000..0ecfaa34
--- /dev/null
+++ b/src/content/dependencies/generateArtistGroupContributionsInfo.js
@@ -0,0 +1,124 @@
+import {stitchArrays, unique} from '../../util/sugar.js';
+
+export default {
+  contentDependencies: ['linkGroup'],
+  extraDependencies: ['html', 'language', 'wikiData'],
+
+  sprawl({groupCategoryData}) {
+    return {
+      groupOrder: groupCategoryData.flatMap(category => category.groups),
+    }
+  },
+
+  query(sprawl, tracksAndAlbums) {
+    const filteredAlbums = tracksAndAlbums.filter(thing => !thing.album);
+    const filteredTracks = tracksAndAlbums.filter(thing => thing.album);
+
+    const allAlbums = unique([
+      ...filteredAlbums,
+      ...filteredTracks.map(track => track.album),
+    ]);
+
+    const allGroupsUnordered = new Set(Array.from(allAlbums).flatMap(album => album.groups));
+    const allGroupsOrdered = sprawl.groupOrder.filter(group => allGroupsUnordered.has(group));
+
+    const mapTemplate = allGroupsOrdered.map(group => [group, 0]);
+    const groupToCountMap = new Map(mapTemplate);
+    const groupToDurationMap = new Map(mapTemplate);
+    const groupToDurationCountMap = new Map(mapTemplate);
+
+    for (const album of filteredAlbums) {
+      for (const group of album.groups) {
+        groupToCountMap.set(group, groupToCountMap.get(group) + 1);
+      }
+    }
+
+    for (const track of filteredTracks) {
+      for (const group of track.album.groups) {
+        groupToCountMap.set(group, groupToCountMap.get(group) + 1);
+        if (track.duration) {
+          groupToDurationMap.set(group, groupToDurationMap.get(group) + track.duration);
+          groupToDurationCountMap.set(group, groupToDurationCountMap.get(group) + 1);
+        }
+      }
+    }
+
+    const groupsSortedByCount =
+      allGroupsOrdered
+        .sort((a, b) => groupToCountMap.get(b) - groupToCountMap.get(a));
+
+    const groupsSortedByDuration =
+      allGroupsOrdered
+        .filter(group => groupToDurationMap.get(group) > 0)
+        .sort((a, b) => groupToDurationMap.get(b) - groupToDurationMap.get(a));
+
+    const groupCounts =
+      groupsSortedByCount
+        .map(group => groupToCountMap.get(group));
+
+    const groupDurations =
+      groupsSortedByDuration
+        .map(group => groupToDurationMap.get(group));
+
+    const groupDurationsApproximate =
+      groupsSortedByDuration
+        .map(group => groupToDurationCountMap.get(group) > 1);
+
+    return {
+      groupsSortedByCount,
+      groupsSortedByDuration,
+      groupCounts,
+      groupDurations,
+      groupDurationsApproximate,
+    };
+  },
+
+  relations(relation, query) {
+    return {
+      groupLinksSortedByCount:
+        query.groupsSortedByCount
+          .map(group => relation('linkGroup', group)),
+
+      groupLinksSortedByDuration:
+        query.groupsSortedByDuration
+          .map(group => relation('linkGroup', group)),
+    };
+  },
+
+  data(query) {
+    return {
+      groupCounts: query.groupCounts,
+      groupDurations: query.groupDurations,
+      groupDurationsApproximate: query.groupDurationsApproximate,
+    };
+  },
+
+  slots: {
+    mode: {
+      validate: v => v.is('count', 'duration'),
+    },
+  },
+
+  generate(data, relations, slots, {language}) {
+    return (
+      language.formatUnitList(
+        (slots.mode === 'count'
+          ? stitchArrays({
+              groupLink: relations.groupLinksSortedByCount,
+              count: data.groupCounts,
+            }).map(({groupLink, count}) =>
+                language.$('artistPage.groupsLine.item.withCount', {
+                  group: groupLink,
+                  count,
+                }))
+          : stitchArrays({
+              groupLink: relations.groupLinksSortedByDuration,
+              duration: data.groupDurations,
+              approximate: data.groupDurationsApproximate,
+            }).map(({groupLink, duration, approximate}) =>
+                language.$('artistPage.groupsLine.item.withDuration', {
+                  group: groupLink,
+                  duration: language.formatDuration(duration, {approximate}),
+                })))));
+  },
+};
diff --git a/src/content/dependencies/generateArtistInfoPage.js b/src/content/dependencies/generateArtistInfoPage.js
index bfb3d601..b2360207 100644
--- a/src/content/dependencies/generateArtistInfoPage.js
+++ b/src/content/dependencies/generateArtistInfoPage.js
@@ -3,6 +3,7 @@ import {getTotalDuration} from '../../util/wiki-data.js';
 
 export default {
   contentDependencies: [
+    'generateArtistGroupContributionsInfo',
     'generateArtistInfoPageArtworksChunkedList',
     'generateArtistInfoPageFlashesChunkedList',
     'generateArtistInfoPageTracksChunkedList',
@@ -26,7 +27,13 @@ export default {
     };
   },
 
-  relations(relation, sprawl, artist) {
+  query(sprawl, artist) {
+    return {
+      allTracks: unique([...artist.tracksAsArtist, ...artist.tracksAsContributor]),
+    };
+  },
+
+  relations(relation, query, sprawl, artist) {
     const relations = {};
     const sections = relations.sections = {};
 
@@ -36,35 +43,6 @@ export default {
     relations.artistNavLinks =
       relation('generateArtistNavLinks', artist);
 
-    /*
-    function getGroupInfo(entries) {
-      const allGroups = new Set();
-      const groupToDuration = new Map();
-      const groupToCount = new Map();
-
-      for (const entry of entries) {
-        for (const group of entry.album.groups) {
-          allGroups.add(group);
-          groupToCount.set(group, (groupToCount.get(group) ?? 0) + 1);
-          groupToDuration.set(group, (groupToDuration.get(group) ?? 0) + entry.duration ?? 0);
-        }
-      }
-
-      const groupInfo =
-        Array.from(allGroups)
-          .map(group => ({
-            groupLink: relation('linkGroup', group),
-            duration: groupToDuration.get(group) ?? 0,
-            count: groupToCount.get(group),
-          }));
-
-      groupInfo.sort((a, b) => b.count - a.count);
-      groupInfo.sort((a, b) => b.duration - a.duration);
-
-      return groupInfo;
-    }
-    */
-
     if (artist.hasAvatar) {
       relations.cover =
         relation('generateCoverArtwork', []);
@@ -82,15 +60,11 @@ export default {
           relation('linkExternal', url));
     }
 
-    if (!empty(artist.tracksAsArtist) || !empty(artist.tracksAsContributor)) {
+    if (!empty(query.allTracks)) {
       const tracks = sections.tracks = {};
       tracks.heading = relation('generateContentHeading');
       tracks.list = relation('generateArtistInfoPageTracksChunkedList', artist);
-
-      // const groupInfo = getGroupInfo(query.trackContributionEntries, 'duration');
-      // if (!empty(groupInfo)) {
-      //   tracks.groupInfo = groupInfo;
-      // }
+      tracks.groupInfo = relation('generateArtistGroupContributionsInfo', query.allTracks);
     }
 
     if (
@@ -108,10 +82,15 @@ export default {
           relation('linkArtistGallery', artist);
       }
 
-      // const groupInfo = getGroupInfo(artContributionEntries, 'count');
-      // if (!empty(groupInfo)) {
-      //   artworks.groupInfo = groupInfo;
-      // }
+      // We intentionally duplicate album data objects when the artist has contributed
+      // at least two of cover art / wallpaper / banner! These each count as one.
+      artworks.groupInfo =
+        relation('generateArtistGroupContributionsInfo', [
+          ...artist.albumsAsCoverArtist,
+          ...artist.albumsAsWallpaperArtist,
+          ...artist.albumsAsBannerArtist,
+          ...artist.tracksAsCoverArtist,
+        ]);
     }
 
     if (sprawl.enableFlashesAndGames && !empty(artist.flashesAsContributor)) {
@@ -169,7 +148,7 @@ export default {
     return relations;
   },
 
-  data(sprawl, artist) {
+  data(query, sprawl, artist) {
     const data = {};
 
     data.name = artist.name;
@@ -179,9 +158,8 @@ export default {
       data.avatarFileExtension = artist.avatarFileExtension;
     }
 
-    const allTracks = unique([...artist.tracksAsArtist, ...artist.tracksAsContributor]);
-    data.totalTrackCount = allTracks.length;
-    data.totalDuration = getTotalDuration(allTracks, {originalReleasesOnly: true});
+    data.totalTrackCount = query.allTracks.length;
+    data.totalDuration = getTotalDuration(query.allTracks, {originalReleasesOnly: true});
 
     return data;
   },
@@ -272,24 +250,12 @@ export default {
                     }),
                 })),
 
-            /*
-            sec.tracks.groupInfo &&
+            // TODO: How to check if a template is blank!?
+            // !html.isBlank(sec.tracks.groupInfo.content) &&
               html.tag('p',
                 language.$('artistPage.musicGroupsLine', {
-                  groups:
-                    language.formatUnitList(
-                      sec.tracks.groupInfo.map(({groupLink, count, duration}) =>
-                        (duration
-                          ? language.$('artistPage.groupsLine.item.withDuration', {
-                              group: groupLink,
-                              duration: language.formatDuration(duration, {approximate: count > 1}),
-                            })
-                          : language.$('artistPage.groupsLine.item.withCount', {
-                              group: groupLink,
-                              count: language.countContributions(count),
-                            })))),
+                  groups: sec.tracks.groupInfo.slot('mode', 'duration'),
                 })),
-            */
 
             sec.tracks.list,
           ],
@@ -302,6 +268,11 @@ export default {
                 title: language.$('artistPage.artList.title'),
               }),
 
+            html.tag('p',
+              language.$('artistPage.artGroupsLine', {
+                groups: sec.artworks.groupInfo.slot('mode', 'count'),
+              })),
+
             sec.artworks.artistGalleryLink &&
               html.tag('p',
                 language.$('artistPage.viewArtGallery.orBrowseList', {
@@ -311,49 +282,6 @@ export default {
                 })),
 
             sec.artworks.list,
-
-            /*
-            sec.artworks.groupInfo &&
-              html.tag('p',
-                language.$('artistPage.artGroupsLine', {
-                  groups:
-                    language.formatUnitList(
-                      sec.artworks.groupInfo.map(({groupLink, count}) =>
-                        language.$('artistPage.groupsLine.item.withCount', {
-                          group: groupLink,
-                          count:
-                            language.countContributions(count),
-                        }))),
-                })),
-            */
-
-            /*
-            html.tag('dl',
-              sec.artworks.chunks.map(({albumLink, date, entries}) => [
-                html.tag('dt',
-                  addAccentsToAlbumLink({albumLink, date, entries})),
-
-                html.tag('dd',
-                  html.tag('ul',
-                    entries
-                      .map(({kind, trackLink, ...properties}) => ({
-                        entry:
-                          (kind === 'trackCover'
-                            ? language.$('artistPage.creditList.entry.track', {
-                                track: trackLink,
-                              })
-                            : html.tag('i',
-                                language.$('artistPage.creditList.entry.album.' + {
-                                  albumWallpaper: 'wallpaperArt',
-                                  albumBanner: 'bannerArt',
-                                  albumCover: 'coverArt',
-                                }[kind]))),
-                        ...properties,
-                      }))
-                      .map(addAccentsToEntry)
-                      .map(entry => html.tag('li', entry)))),
-              ])),
-            */
           ],
 
           sec.flashes && [