« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/util/wiki-data.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/wiki-data.js')
-rw-r--r--src/util/wiki-data.js105
1 files changed, 73 insertions, 32 deletions
diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js
index 0eb86a1e..89c621c5 100644
--- a/src/util/wiki-data.js
+++ b/src/util/wiki-data.js
@@ -181,6 +181,7 @@ export function sortByName(data, {
 }
 
 export function sortByDate(data, {
+  latestFirst = false,
   getDate = (o) => o.date,
 } = {}) {
   return data.sort((a, b) => {
@@ -191,7 +192,7 @@ export function sortByDate(data, {
     // together in the same array. If that's the case, we put all items
     // without dates at the end.
     if (ad && bd) {
-      return ad - bd;
+      return (latestFirst ? bd - ad : ad - bd);
     } else if (ad) {
       return -1;
     } else if (bd) {
@@ -206,35 +207,52 @@ export function sortByDate(data, {
   });
 }
 
-export function sortByPositionInAlbum(data) {
+export function sortByPositionInParent(data, {
+  getParent,
+  getChildren,
+}) {
   return data.sort((a, b) => {
-    const aa = a.album;
-    const ba = b.album;
+    const parentA = getParent(a);
+    const parentB = getParent(b);
 
-    // Don't change the sort when the two tracks are from separate albums.
-    // This function doesn't change the order of albums or try to "merge"
-    // two separated chunks of tracks from the same album together.
-    if (aa !== ba) {
+    // Don't change the sort when the two items are from separate parents.
+    // This function doesn't change the order of parents or try to "merge"
+    // two separated chunks of items from the same parent together.
+    if (parentA !== parentB) {
       return 0;
     }
 
-    // Don't change the sort when only one (or neither) item is actually
-    // a track (i.e. has an album).
-    if (!aa || !ba) {
+    // Don't change the sort when either (or both) of the items doesn't
+    // even have a parent (e.g. it's the passed data is a mixed array of
+    // children and parents).
+    if (!parentA || !parentB) {
       return 0;
     }
 
-    const ai = aa.tracks.indexOf(a);
-    const bi = ba.tracks.indexOf(b);
+    const indexA = getChildren(parentA).indexOf(a);
+    const indexB = getChildren(parentB).indexOf(b);
 
-    // There's no reason this two-way reference (a track's album and the
-    // album's track list) should be broken, but if for any reason it is,
-    // don't change the sort.
-    if (ai === -1 || bi === -1) {
+    // If the getParent/getChildren relationship doesn't go both ways for
+    // some reason, don't change the sort.
+    if (indexA === -1 || indexB === -1) {
       return 0;
     }
 
-    return ai - bi;
+    return indexA - indexB;
+  });
+}
+
+export function sortByPositionInAlbum(data) {
+  return sortByPositionInParent(data, {
+    getParent: track => track.album,
+    getChildren: album => album.tracks,
+  });
+}
+
+export function sortByPositionInFlashAct(data) {
+  return sortByPositionInParent(data, {
+    getParent: flash => flash.act,
+    getChildren: act => act.flashes,
   });
 }
 
@@ -242,7 +260,7 @@ export function sortByPositionInAlbum(data) {
 // set of arbitrary given conditions is true first. If no conditions are met
 // for a given item, it's moved over to the end!
 export function sortByConditions(data, conditions) {
-  data.sort((a, b) => {
+  return data.sort((a, b) => {
     const ai = conditions.findIndex((f) => f(a));
     const bi = conditions.findIndex((f) => f(b));
 
@@ -292,18 +310,8 @@ export function sortChronologically(data, {
   getName,
   getDate,
 } = {}) {
-  if (latestFirst) {
-    // Double reverse: Since we reverse after sorting by date, also reverse
-    // after sorting A-Z, so the second reverse restores A-Z relative
-    // positioning (for entries with the same date).
-    sortAlphabetically(data, {getDirectory, getName});
-    data.reverse();
-    sortByDate(data, {getDate});
-    data.reverse();
-  } else {
-    sortAlphabetically(data, {getDirectory, getName});
-    sortByDate(data, {getDate});
-  }
+  sortAlphabetically(data, {getDirectory, getName});
+  sortByDate(data, {latestFirst, getDate});
   return data;
 }
 
@@ -316,6 +324,7 @@ export function sortChronologically(data, {
 //
 // This function also works for data lists which contain only tracks.
 export function sortAlbumsTracksChronologically(data, {
+  latestFirst = false,
   getDate,
 } = {}) {
   // Sort albums before tracks...
@@ -333,7 +342,39 @@ export function sortAlbumsTracksChronologically(data, {
   // released on the same date, they'll still be grouped together by album,
   // and tracks within an album will retain their relative positioning (i.e.
   // stay in the same order as part of the album's track listing).
-  sortByDate(data, {getDate});
+  sortByDate(data, {latestFirst, getDate});
+
+  return data;
+}
+
+export function sortFlashesChronologically(data, {
+  latestFirst = false,
+  getDate,
+} = {}) {
+  // Flash acts don't actually have any identifying properties because they
+  // don't have dedicated pages (yet), so don't have a directory. Make up a
+  // fake key identifying them so flashes can be grouped together.
+  const flashActs = new Set(data.map(flash => flash.act));
+  const flashActIdentifiers = new Map();
+
+  let counter = 0;
+  for (const act of flashActs) {
+    flashActIdentifiers.set(act, ++counter);
+  }
+
+  // Group flashes by act...
+  data.sort((a, b) => {
+    return flashActIdentifiers.get(a.act) - flashActIdentifiers.get(b.act);
+  });
+
+  // Sort flashes by position in act...
+  sortByPositionInFlashAct(data);
+
+  // ...and finally sort by date. If flashes from more than one act were
+  // released on the same date, they'll still be grouped together by act,
+  // and flashes within an act will retain their relative positioning (i.e.
+  // stay in the same order as the act's flash listing).
+  sortByDate(data, {latestFirst, getDate});
 
   return data;
 }