« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/content/dependencies/listAlbumsByDuration.js20
-rw-r--r--src/content/dependencies/listAlbumsByTracks.js20
-rw-r--r--src/content/dependencies/listArtistsByCommentaryEntries.js55
-rw-r--r--src/content/dependencies/listArtistsByContributions.js68
-rw-r--r--src/content/dependencies/listArtistsByName.js55
-rw-r--r--src/listing-spec.js34
-rw-r--r--src/util/wiki-data.js39
7 files changed, 203 insertions, 88 deletions
diff --git a/src/content/dependencies/listAlbumsByDuration.js b/src/content/dependencies/listAlbumsByDuration.js
index e922ebc..650a5d1 100644
--- a/src/content/dependencies/listAlbumsByDuration.js
+++ b/src/content/dependencies/listAlbumsByDuration.js
@@ -1,5 +1,5 @@
 import {stitchArrays} from '../../util/sugar.js';
-import {getTotalDuration} from '../../util/wiki-data.js';
+import {filterByCount, getTotalDuration, sortByCount} from '../../util/wiki-data.js';
 
 export default {
   contentDependencies: ['generateListingPage', 'linkAlbum'],
@@ -10,17 +10,13 @@ export default {
   },
 
   query({albumData}, spec) {
-    const albumToDuration =
-      new Map(albumData.map(album => [album, getTotalDuration(album.tracks)]));
+    const albums = albumData.slice();
+    const durations = albums.map(album => getTotalDuration(album.tracks));
 
-    return {
-      spec,
+    filterByCount(albums, durations);
+    sortByCount(albums, durations, {greatestFirst: true});
 
-      albums:
-        albumData
-          .filter(album => albumToDuration.get(album) > 0)
-          .sort((a, b) => albumToDuration.get(b) - albumToDuration.get(a)),
-    };
+    return {spec, albums, durations};
   },
 
   relations(relation, query) {
@@ -35,9 +31,7 @@ export default {
 
   data(query) {
     return {
-      durations:
-        query.albums
-          .map(album => getTotalDuration(album.tracks)),
+      durations: query.durations,
     };
   },
 
diff --git a/src/content/dependencies/listAlbumsByTracks.js b/src/content/dependencies/listAlbumsByTracks.js
index acec5da..c31609b 100644
--- a/src/content/dependencies/listAlbumsByTracks.js
+++ b/src/content/dependencies/listAlbumsByTracks.js
@@ -1,4 +1,5 @@
-import {empty, stitchArrays} from '../../util/sugar.js';
+import {stitchArrays} from '../../util/sugar.js';
+import {filterByCount, sortByCount} from '../../util/wiki-data.js';
 
 export default {
   contentDependencies: ['generateListingPage', 'linkAlbum'],
@@ -9,14 +10,13 @@ export default {
   },
 
   query({albumData}, spec) {
-    return {
-      spec,
+    const albums = albumData.slice();
+    const counts = albums.map(album => album.tracks.length);
 
-      albums:
-        albumData
-          .filter(album => !empty(album.tracks))
-          .sort((a, b) => b.tracks.length - a.tracks.length),
-    };
+    filterByCount(albums, counts);
+    sortByCount(albums, counts, {greatestFirst: true});
+
+    return {spec, albums, counts};
   },
 
   relations(relation, query) {
@@ -31,9 +31,7 @@ export default {
 
   data(query) {
     return {
-      counts:
-        query.albums
-          .map(album => album.tracks.length),
+      counts: query.counts,
     };
   },
 
diff --git a/src/content/dependencies/listArtistsByCommentaryEntries.js b/src/content/dependencies/listArtistsByCommentaryEntries.js
new file mode 100644
index 0000000..eae6dd6
--- /dev/null
+++ b/src/content/dependencies/listArtistsByCommentaryEntries.js
@@ -0,0 +1,55 @@
+import {stitchArrays} from '../../util/sugar.js';
+import {filterByCount, sortByCount} from '../../util/wiki-data.js';
+
+export default {
+  contentDependencies: ['generateListingPage', 'linkArtist'],
+  extraDependencies: ['language', 'wikiData'],
+
+  sprawl({artistData}) {
+    return {artistData};
+  },
+
+  query({artistData}, spec) {
+    const artists = artistData.slice();
+    const counts =
+      artists.map(artist =>
+        artist.tracksAsCommentator.length +
+        artist.albumsAsCommentator.length);
+
+    filterByCount(artists, counts);
+    sortByCount(artists, counts, {greatestFirst: true});
+
+    return {artists, counts, spec};
+  },
+
+  relations(relation, query) {
+    return {
+      page:
+        relation('generateListingPage', query.spec),
+
+      artistLinks:
+        query.artists
+          .map(artist => relation('linkArtist', artist)),
+    };
+  },
+
+  data(query) {
+    return {
+      counts: query.counts,
+    };
+  },
+
+  generate(data, relations, {language}) {
+    return relations.page.slots({
+      type: 'rows',
+      rows:
+        stitchArrays({
+          link: relations.artistLinks,
+          count: data.counts,
+        }).map(({link, count}) => ({
+            artist: link,
+            entries: language.countCommentaryEntries(count, {unit: true}),
+          })),
+    });
+  },
+};
diff --git a/src/content/dependencies/listArtistsByContributions.js b/src/content/dependencies/listArtistsByContributions.js
index 78c8c1a..ae00fc6 100644
--- a/src/content/dependencies/listArtistsByContributions.js
+++ b/src/content/dependencies/listArtistsByContributions.js
@@ -1,4 +1,5 @@
 import {stitchArrays, unique} from '../../util/sugar.js';
+import {filterByCount, sortByCount} from '../../util/wiki-data.js';
 
 export default {
   contentDependencies: ['generateListingPage', 'linkArtist'],
@@ -12,34 +13,45 @@ export default {
   },
 
   query(sprawl, spec) {
-    const query = {spec};
+    const query = {
+      spec,
+      enableFlashesAndGames: sprawl.enableFlashesAndGames,
+    };
+
+    const queryContributionInfo = (artistsKey, countsKey, fn) => {
+      const artists = sprawl.artistData.slice();
+      const counts = artists.map(artist => fn(artist));
 
-    const queryContributionInfo = fn =>
-      sprawl.artistData
-        .map(artist => ({artist, contributions: fn(artist)}))
-        .filter(({contributions}) => contributions)
-        .sort((a, b) => b.contributions - a.contributions);
+      filterByCount(artists, counts);
+      sortByCount(artists, counts, {greatestFirst: true});
 
-    query.enableFlashesAndGames =
-      sprawl.enableFlashesAndGames;
+      query[artistsKey] = artists;
+      query[countsKey] = counts;
+    };
 
-    query.trackContributionInfo =
-      queryContributionInfo(artist =>
+    queryContributionInfo(
+      'artistsByTrackContributions',
+      'countsByTrackContributions',
+      artist =>
         unique([
           ...artist.tracksAsContributor,
           ...artist.tracksAsArtist,
         ]).length);
 
-    query.artworkContributionInfo =
-      queryContributionInfo(artist =>
+    queryContributionInfo(
+      'artistsByArtworkContributions',
+      'countsByArtworkContributions',
+      artist =>
         artist.tracksAsCoverArtist.length +
         artist.albumsAsCoverArtist.length +
         artist.albumsAsWallpaperArtist.length +
         artist.albumsAsBannerArtist.length);
 
     if (sprawl.enableFlashesAndGames) {
-      query.flashContributionInfo =
-        queryContributionInfo(artist =>
+      queryContributionInfo(
+        'artistsByFlashContributions',
+        'countsByFlashContributions',
+        artist =>
           artist.flashesAsContributor.length);
     }
 
@@ -53,17 +65,17 @@ export default {
       relation('generateListingPage', query.spec);
 
     relations.artistLinksByTrackContributions =
-      query.trackContributionInfo
-        .map(({artist}) => relation('linkArtist', artist));
+      query.artistsByTrackContributions
+        .map(artist => relation('linkArtist', artist));
 
     relations.artistLinksByArtworkContributions =
-      query.artworkContributionInfo
-        .map(({artist}) => relation('linkArtist', artist));
+      query.artistsByArtworkContributions
+        .map(artist => relation('linkArtist', artist));
 
     if (query.enableFlashesAndGames) {
       relations.artistLinksByFlashContributions =
-        query.flashContributionInfo
-          .map(({artist}) => relation('linkArtist', artist));
+        query.artistsByFlashContributions
+          .map(artist => relation('linkArtist', artist));
     }
 
     return relations;
@@ -72,21 +84,13 @@ export default {
   data(query) {
     const data = {};
 
-    data.enableFlashesAndGames =
-      query.enableFlashesAndGames;
-
-    data.countsByTrackContributions =
-      query.trackContributionInfo
-        .map(({contributions}) => contributions);
+    data.enableFlashesAndGames = query.enableFlashesAndGames;
 
-    data.countsByArtworkContributions =
-      query.artworkContributionInfo
-        .map(({contributions}) => contributions);
+    data.countsByTrackContributions = query.countsByTrackContributions;
+    data.countsByArtworkContributions = query.countsByArtworkContributions;
 
     if (query.enableFlashesAndGames) {
-      data.countsByFlashContributions =
-        query.flashContributionInfo
-          .map(({contributions}) => contributions);
+      data.countsByFlashContributions = query.countsByFlashContributions;
     }
 
     return data;
diff --git a/src/content/dependencies/listArtistsByName.js b/src/content/dependencies/listArtistsByName.js
new file mode 100644
index 0000000..1b93eca
--- /dev/null
+++ b/src/content/dependencies/listArtistsByName.js
@@ -0,0 +1,55 @@
+import {stitchArrays} from '../../util/sugar.js';
+
+import {
+  getArtistNumContributions,
+  sortAlphabetically,
+} from '../../util/wiki-data.js';
+
+export default {
+  contentDependencies: ['generateListingPage', 'linkArtist'],
+  extraDependencies: ['language', 'wikiData'],
+
+  sprawl({artistData}) {
+    return {artistData};
+  },
+
+  query({artistData}, spec) {
+    return {
+      spec,
+
+      artists: sortAlphabetically(artistData.slice()),
+    };
+  },
+
+  relations(relation, query) {
+    return {
+      page: relation('generateListingPage', query.spec),
+
+      artistLinks:
+        query.artists
+          .map(album => relation('linkArtist', album)),
+    };
+  },
+
+  data(query) {
+    return {
+      counts:
+        query.artists
+          .map(artist => getArtistNumContributions(artist)),
+    };
+  },
+
+  generate(data, relations, {language}) {
+    return relations.page.slots({
+      type: 'rows',
+      rows:
+        stitchArrays({
+          link: relations.artistLinks,
+          count: data.counts,
+        }).map(({link, count}) => ({
+            artist: link,
+            contributions: language.countContributions(count, {unit: true}),
+          })),
+    });
+  },
+};
diff --git a/src/listing-spec.js b/src/listing-spec.js
index f0f2c8e..1b0fe97 100644
--- a/src/listing-spec.js
+++ b/src/listing-spec.js
@@ -59,21 +59,7 @@ listingSpec.push({
 listingSpec.push({
   directory: 'artists/by-name',
   stringsKey: 'listArtists.byName',
-
-  data: ({wikiData: {artistData}}) =>
-    sortAlphabetically(artistData.slice())
-      .map(artist => ({
-        artist,
-        contributions: getArtistNumContributions(artist),
-      })),
-
-  row: ({artist, contributions}, {language, link}) =>
-    language.$('listingPage.listArtists.byName.item', {
-      artist: link.artist(artist),
-      contributions: language.countContributions(contributions, {
-        unit: true,
-      }),
-    }),
+  contentFunction: 'listArtistsByName',
 });
 
 listingSpec.push({
@@ -85,23 +71,7 @@ listingSpec.push({
 listingSpec.push({
   directory: 'artists/by-commentary',
   stringsKey: 'listArtists.byCommentary',
-
-  data: ({wikiData: {artistData}}) =>
-    artistData
-      .map(artist => ({
-        artist,
-        entries:
-          artist.tracksAsCommentator.length +
-          artist.albumsAsCommentator.length,
-      }))
-      .filter(({entries}) => entries)
-      .sort((a, b) => b.entries - a.entries),
-
-  row: ({artist, entries}, {language, link}) =>
-    language.$('listingPage.listArtists.byCommentary.item', {
-      artist: link.artist(artist),
-      entries: language.countCommentaryEntries(entries, {unit: true}),
-    }),
+  contentFunction: 'listArtistsByCommentaryEntries',
 });
 
 listingSpec.push({
diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js
index da8312f..0ee474a 100644
--- a/src/util/wiki-data.js
+++ b/src/util/wiki-data.js
@@ -3,6 +3,7 @@
 import {
   accumulateSum,
   empty,
+  stitchArrays,
   unique,
 } from './sugar.js';
 
@@ -208,6 +209,44 @@ export function sortByDate(data, {
   });
 }
 
+// Funky sort which takes a data set and a corresponding list of "counts",
+// which are really arbitrary numbers representing some property of each data
+// object defined by the caller. It sorts and mutates *both* of these, so the
+// sorted data will still correspond to the same indexed count.
+export function sortByCount(data, counts, {
+  greatestFirst = false,
+} = {}) {
+  const thingToCount = new Map(
+    stitchArrays({thing: data, count: counts})
+      .map(({thing, count}) => [thing, count]));
+
+  data.sort((a, b) =>
+    (greatestFirst
+      ? thingToCount.get(b) - thingToCount.get(a)
+      : thingToCount.get(a) - thingToCount.get(b)));
+
+  counts.sort((a, b) =>
+    (greatestFirst
+      ? b - a
+      : a - b));
+
+  return data;
+}
+
+// Corresponding filter function for the above sort. By default, items whose
+// corresponding count is zero will be removed.
+export function filterByCount(data, counts, {
+  min = 1,
+  max = Infinity,
+} = {}) {
+  for (let i = counts.length - 1; i >= 0; i--) {
+    if (counts[i] < min || counts[i] > max) {
+      data.splice(i, 1);
+      counts.splice(i, 1);
+    }
+  }
+}
+
 export function sortByPositionInParent(data, {
   getParent,
   getChildren,