« get me outta code hell

content: generateDividedTrackList: context groups - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2026-04-02 23:27:55 -0300
committer(quasar) nebula <qznebula@protonmail.com>2026-04-02 23:27:55 -0300
commit818e89c7ee0a426ac5f66a4079c70e047627a7f2 (patch)
tree489d6651767e7b7214324e8dfbc47fed1d2deda6 /src/content/dependencies
parentb250e91a74b244cc5decd79f5604cfb8a811421a (diff)
content: generateDividedTrackList: context groups
Diffstat (limited to 'src/content/dependencies')
-rw-r--r--src/content/dependencies/generateDividedTrackList.js145
1 files changed, 96 insertions, 49 deletions
diff --git a/src/content/dependencies/generateDividedTrackList.js b/src/content/dependencies/generateDividedTrackList.js
index ea349ec8..584eb920 100644
--- a/src/content/dependencies/generateDividedTrackList.js
+++ b/src/content/dependencies/generateDividedTrackList.js
@@ -1,4 +1,5 @@
-import {empty, filterMultipleArrays, stitchArrays} from '#sugar';
+import {empty, filterMultipleArrays, runs, stitchArrays, unique} from '#sugar';
+import {TupleMapForBabies} from '#wiki-data';
 
 export default {
   sprawl: ({wikiInfo}) => ({
@@ -6,40 +7,81 @@ export default {
       wikiInfo.divideTrackListsByGroups,
   }),
 
-  query(sprawl, tracks, _contextTrack) {
-    const dividingGroups = sprawl.divideTrackListsByGroups;
+  query(sprawl, tracks, contextTrack) {
+    const wikiDividingGroups = sprawl.divideTrackListsByGroups;
 
-    const groupings = new Map();
+    const contextDividingGroups =
+      contextTrack.groups
+        .filter(group => !wikiDividingGroups.includes(group));
+
+    const contextGroupRuns =
+      Array.from(runs(contextDividingGroups));
+
+    const groupings = new TupleMapForBabies('strong');
     const ungroupedTracks = [];
 
-    // Entry order matters! Add blank lists for each group
-    // in the order that those groups are provided.
-    for (const group of dividingGroups) {
-      groupings.set(group, []);
-    }
+    const order = [
+      ...contextGroupRuns,
+      ...wikiDividingGroups.map(group => [group]),
+    ];
 
     for (const track of tracks) {
-      const firstMatchingGroup =
-        dividingGroups.find(group => group.albums.includes(track.album));
+      let run;
+      getRun: {
+        run =
+          contextDividingGroups
+            .filter(group => track.groups.includes(group));
+
+        if (!empty(run)) {
+          break getRun;
+        }
+
+        const wikiGroup =
+          wikiDividingGroups.find(group => track.groups.includes(group));
+
+        if (wikiGroup) {
+          run = [wikiGroup];
+          break getRun;
+        }
 
-      if (firstMatchingGroup) {
-        groupings.get(firstMatchingGroup).push(track);
-      } else {
         ungroupedTracks.push(track);
+        continue;
+      }
+
+      if (groupings.has(...run)) {
+        groupings.get(...run).push(track);
+      } else {
+        groupings.set(...run, [track]);
       }
     }
 
-    const groups = Array.from(groupings.keys());
-    const groupedTracks = Array.from(groupings.values());
+    let groupingGroups = order.slice();
+    const groupedTracks = order.map(run => groupings.get(...run) ?? []);
 
-    // Drop the empty lists, so just the groups which
-    // at least a single track matched are left.
     filterMultipleArrays(
-      groups,
+      groupingGroups,
       groupedTracks,
-      (_group, tracks) => !empty(tracks));
-
-    return {groups, groupedTracks, ungroupedTracks};
+      (_groups, tracks) => !empty(tracks));
+
+    const presentContextDividingGroups =
+      unique(groupingGroups.flat())
+        .filter(group => contextDividingGroups.includes(group));
+
+    const uninformativeGroups =
+      presentContextDividingGroups.filter((group, index) =>
+        presentContextDividingGroups
+          .slice(0, index)
+          .some(earlier =>
+            groupingGroups.every(run =>
+              run.includes(earlier) && run.includes(group) ||
+             !run.includes(earlier) && !run.includes(group))));
+
+    groupingGroups =
+      groupingGroups.map(groups =>
+        groups.filter(group =>
+          !uninformativeGroups.includes(group)));
+
+    return {groupingGroups, groupedTracks, ungroupedTracks};
   },
 
   relations: (relation, query, sprawl, tracks, contextTrack) => ({
@@ -52,8 +94,9 @@ export default {
       relation('generateContentHeading'),
 
     groupLinks:
-      query.groups
-        .map(group => relation('linkGroup', group)),
+      query.groupingGroups
+        .map(groups => groups
+          .map(group => relation('linkGroup', group))),
 
     groupedTrackLists:
       query.groupedTracks
@@ -67,8 +110,9 @@ export default {
 
   data: (query, _sprawl, _tracks) => ({
     groupNames:
-      query.groups
-        .map(group => group.name),
+      query.groupingGroups
+        .map(groups => groups
+          .map(group => group.name)),
   }),
 
   slots: {
@@ -85,33 +129,36 @@ export default {
 
       language.encapsulate('trackList', listCapsule => [
         stitchArrays({
-          groupName: data.groupNames,
-          groupLink: relations.groupLinks,
+          groupNames: data.groupNames,
+          groupLinks: relations.groupLinks,
           trackList: relations.groupedTrackLists,
         }).map(({
-            groupName,
-            groupLink,
+            groupNames,
+            groupLinks,
             trackList,
           }) => [
-            language.encapsulate(listCapsule, 'fromGroup', capsule =>
-              (slots.headingString
-                ? relations.contentHeading.clone().slots({
-                    tag: 'dt',
-
-                    title:
-                      language.$(capsule, {
-                        group: groupLink.slot('color', false),
-                      }),
-
-                    stickyTitle:
-                      language.$(slots.headingString, 'sticky', 'fromGroup', {
-                        group: groupName,
-                      }),
-                  })
-                : html.tag('dt',
-                    language.$(capsule, {
-                      group: groupLink.slot('color', false),
-                    })))),
+            language.encapsulate(listCapsule, 'fromGroup', capsule => {
+              const title =
+                language.$(capsule, {
+                  group:
+                    language.formatConjunctionList(
+                      groupLinks.map(link => link.slot('color', false))),
+                });
+
+              if (slots.headingString) {
+                return relations.contentHeading.clone().slots({
+                  tag: 'dt',
+                  title,
+                  stickyTitle:
+                    language.$(slots.headingString, 'sticky', 'fromGroup', {
+                      group:
+                        language.formatConjunctionList(groupNames),
+                    }),
+                });
+              } else {
+                return html.tag('dt', title);
+              }
+            }),
 
             html.tag('dd', trackList),
           ]),