« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies/generateDividedTrackList.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/dependencies/generateDividedTrackList.js')
-rw-r--r--src/content/dependencies/generateDividedTrackList.js185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/content/dependencies/generateDividedTrackList.js b/src/content/dependencies/generateDividedTrackList.js
new file mode 100644
index 00000000..e89f08db
--- /dev/null
+++ b/src/content/dependencies/generateDividedTrackList.js
@@ -0,0 +1,185 @@
+import {empty, filterMultipleArrays, runs, stitchArrays, unique} from '#sugar';
+import {TupleMapForBabies} from '#wiki-data';
+
+export default {
+  sprawl: ({wikiInfo}) => ({
+    divideTrackListsByGroups:
+      wikiInfo.divideTrackListsByGroups,
+  }),
+
+  query(sprawl, tracks, contextTrack) {
+    const wikiDividingGroups = sprawl.divideTrackListsByGroups;
+
+    const contextDividingGroups =
+      contextTrack.groups
+        .filter(group => !wikiDividingGroups.includes(group))
+        .filter(group => group.useForDividingReferenceLists);
+
+    const contextGroupRuns =
+      Array.from(runs(contextDividingGroups));
+
+    const groupings = new TupleMapForBabies('strong');
+    const ungroupedTracks = [];
+
+    const order = [
+      ...contextGroupRuns,
+      ...wikiDividingGroups.map(group => [group]),
+    ];
+
+    for (const track of tracks) {
+      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;
+        }
+
+        ungroupedTracks.push(track);
+        continue;
+      }
+
+      if (groupings.has(...run)) {
+        groupings.get(...run).push(track);
+      } else {
+        groupings.set(...run, [track]);
+      }
+    }
+
+    let groupingGroups = order.slice();
+    const groupedTracks = order.map(run => groupings.get(...run) ?? []);
+
+    filterMultipleArrays(
+      groupingGroups,
+      groupedTracks,
+      (_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) => ({
+    flatList:
+      (empty(sprawl.divideTrackListsByGroups)
+        ? relation('generateNearbyTrackList', tracks, contextTrack, [])
+        : null),
+
+    contentHeading:
+      relation('generateContentHeading'),
+
+    groupLinks:
+      query.groupingGroups
+        .map(groups => groups
+          .map(group => relation('linkGroup', group))),
+
+    groupedTrackLists:
+      query.groupedTracks
+        .map(tracks => relation('generateNearbyTrackList', tracks, contextTrack, [])),
+
+    ungroupedTrackList:
+      (empty(query.ungroupedTracks)
+        ? null
+        : relation('generateNearbyTrackList', query.ungroupedTracks, contextTrack, [])),
+  }),
+
+  data: (query, _sprawl, _tracks) => ({
+    groupNames:
+      query.groupingGroups
+        .map(groups => groups
+          .map(group => group.name)),
+  }),
+
+  slots: {
+    headingString: {
+      type: 'string',
+    },
+  },
+
+  generate: (data, relations, slots, {html, language}) =>
+    relations.flatList ??
+
+    html.tag('dl', {class: 'division-list'},
+      {[html.onlyIfContent]: true},
+
+      language.encapsulate('trackList', listCapsule => [
+        stitchArrays({
+          groupNames: data.groupNames,
+          groupLinks: relations.groupLinks,
+          trackList: relations.groupedTrackLists,
+        }).map(({
+            groupNames,
+            groupLinks,
+            trackList,
+          }) => [
+            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),
+          ]),
+
+        relations.ungroupedTrackList && [
+          language.encapsulate(listCapsule, 'fromOther', capsule =>
+            (slots.headingString
+              ? relations.contentHeading.clone().slots({
+                  tag: 'dt',
+
+                  title:
+                    language.$(capsule),
+
+                  stickyTitle:
+                    language.$(slots.headingString, 'sticky', 'fromOther'),
+                })
+              : html.tag('dt',
+                  language.$(capsule)))),
+
+          html.tag('dd', relations.ungroupedTrackList),
+        ],
+      ])),
+};