« get me outta code hell

http-music - Command-line music player + utils (not a server!)
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/pickers2.js66
-rw-r--r--todo.txt9
2 files changed, 68 insertions, 7 deletions
diff --git a/src/pickers2.js b/src/pickers2.js
index efae124..f1b53eb 100644
--- a/src/pickers2.js
+++ b/src/pickers2.js
@@ -14,7 +14,7 @@ const _seedRandom = require('seed-random')
 // Picker state is used to contain information specific to that picker (for example, the seed a shuffle picker uses, or sorting methods).
 // Uncertain on how to handle serialization of tracks.. some tracks may appear twice in the same playlist (or two tracks of the same name appear); in this case the serialized path to the two track appearances is the same, when they really refer to two separate instances of the track within the playlist. Could track serialization instead be index-based (rather than name-based)..?
 
-const { flattenGrouplike } = require('./playlist-utils')
+const { flattenGrouplike, isGroup } = require('./playlist-utils')
 
 class HistoryController {
   constructor(playlist, picker, pickerOptions = {}) {
@@ -84,10 +84,27 @@ class HistoryController {
   }
 }
 
-function shuffleGroups(grouplike) {
+function shuffleGroups(grouplike, seed) {
+  let newSeed = seed
+
   if (isGroup(grouplike) && grouplike.items.every(isGroup)) {
-    const items = shuffleArray(grouplike.items.map(shuffleGroups))
-    return Object.assign({}, grouplike, {items})
+    const newItems = []
+    for (let item of grouplike.items) {
+      const returnGrouplike = shuffleGroups(item, newSeed)
+
+      if (returnGrouplike.hasOwnProperty('newSeed')) {
+        newSeed = returnGrouplike.newSeed
+        delete returnGrouplike.newSeed
+      }
+
+      newItems.push(returnGrouplike)
+    }
+
+    const shuffledItems = shuffleArray(newItems, newSeed)
+    newSeed = shuffledItems.newSeed
+    delete shuffledItems.newSeed
+
+    return Object.assign({}, grouplike, {items: shuffledItems, newSeed})
   } else {
     return grouplike
   }
@@ -163,9 +180,9 @@ function sortFlattenGrouplike(grouplike, sort, seed) {
   }
 
   if (sort === 'shuffle-groups' || sort === 'shuffled-groups') {
-    const ret = flattenGrouplike(shuffleGroups(grouplike), seed)
-    const items = Array.from(ret)
-    const { newSeed } = ret
+    const shuffled = shuffleGroups(grouplike, seed)
+    const { newSeed } = shuffled
+    const { items } = flattenGrouplike(shuffled)
     return {items, newSeed}
   }
 }
@@ -320,4 +337,39 @@ if (require.main === module) {
   hc_st3.timelineFillSize = 5
   hc_st3.fillTimeline()
   console.log(hc_st3.timeline)
+
+  console.log('---------------')
+  console.log('shuffle-groups:')
+  console.log('(different playlist used here)')
+
+  const playlist2 = {items: [
+    {items: [
+      {x: 'A-a'}, {x: 'A-b'}, {x: 'A-c'}
+    ]},
+    {items: [
+      {x: 'B-a'}, {x: 'B-b'}
+    ]},
+    {items: [
+      {items: [
+        {x: 'C-1-a'}, {x: 'C-1-b'}
+      ]},
+      {items: [
+        {x: 'C-2-a'}, {x: 'C-2-b'}
+      ]}
+    ]}
+  ]}
+
+  console.log('seed = baz')
+  console.log(' - should output the same thing every time')
+  const hc_sg = new HistoryController(playlist2, generalPicker, {sort: 'shuffle-groups', loop: 'loop', seed: '13324iou321324i234123'})
+  hc_sg.timelineFillSize = 3 + 2 + (2 + 2)
+  hc_sg.fillTimeline()
+  console.log(hc_sg.timeline)
+
+  console.log('seed = undefined')
+  console.log('- should output something random each time')
+  const hc_sg2 = new HistoryController(playlist2, generalPicker, {sort: 'shuffle-groups', loop: 'loop'})
+  hc_sg2.timelineFillSize = 3 + 2 + (2 + 2)
+  hc_sg2.fillTimeline()
+  console.log(hc_sg2.timeline)
 }
diff --git a/todo.txt b/todo.txt
index 1706f0d..5cde299 100644
--- a/todo.txt
+++ b/todo.txt
@@ -323,6 +323,7 @@ TODO: Fix the shuffle players, which don't really work anymore (they more or
       (Done!)
 
 TODO: Also fix the shuffle-groups player.
+      (Done!)
 
 TODO: Consider adding pick-random back, in some way or another?
 
@@ -330,3 +331,11 @@ TODO: The concepts of importing and adding keybindings isn't very intuitive..
 
 TODO: A way to export the "timeline" playlist (though we'll need a better
       term) - that is, the flat result of the picker - would be awesome!
+
+TODO: I'm really, really bad at seeding randomness. Aaaaaa. Aaaaaaa. Aaa.
+      AAAAAAA. (Fix the code. Unless it's working right already. Hmm.)
+
+TODO: Now that we're using seeded randomness, generating the entire timeline
+      every time we want to call the picker is definitely really slow. There
+      should be some way to make it faster. (Maybe store the playlist on the
+      mutable options object?).