« get me outta code hell

pickers.js « src - http-music - Command-line music player + utils (not a server!)
about summary refs log tree commit diff
path: root/src/pickers.js
blob: ec4d629b8902038c4d66c151c07b7acf4714b09f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
'use strict'

const { flattenGrouplike } = require('./playlist-utils')

function makeLoopingOrderedPlaylistPicker(grouplike) {
  // Looping ordered playlist picker - this plays all the tracks in a group
  // in order, while looping the same order forever.

  const flatGroup = flattenGrouplike(grouplike)
  let index = 0

  return function() {
    if (index >= flatGroup.items.length) {
      index = 0
    }

    const picked = flatGroup.items[index]
    index++
    return picked
  }
}

function makeNonLoopingOrderedPlaylistPicker(grouplike) {
  // Ordered playlist picker - this plays all the tracks in a group in
  // order, after flattening it.

  const flatGroup = flattenGrouplike(grouplike)
  let index = 0

  return function() {
    if (index < flatGroup.items.length) {
      const picked = flatGroup.items[index]
      index++
      return picked
    } else {
      return null
    }
  }
}

function makeLoopingShufflePlaylistPicker(grouplike) {
  // Shuffle playlist picker - this selects a random track at any index in
  // the playlist, after flattening it.

  const flatGroup = flattenGrouplike(grouplike)

  return function() {
    if (flatGroup.items.length) {
      const index = Math.floor(Math.random() * flatGroup.items.length)
      return flatGroup.items[index]
    } else {
      return null
    }
  }
}

function makeNonLoopingShufflePlaylistPicker(grouplike) {
  // No-loop shuffle playlist picker - this takes a playlist and randomly
  // shuffles the order of the items in it, then uses that as an "ordered"
  // playlist (i.e. it plays all the items in it then stops).

  const flatGroup = flattenGrouplike(grouplike)
  const items = shuffleArray(flatGroup.items)

  return function() {
    if (items.length) {
      return items.splice(0, 1)[0]
    } else {
      return null
    }
  }
}

function shuffleArray(array) {
  // Shuffles the items in an array. Super-interesting post on how it works:
  // https://bost.ocks.org/mike/shuffle/

  const workingArray = array.slice(0)

  let m = array.length

  while (m) {
    let i = Math.floor(Math.random() * m)
    m--

    // Stupid lol; avoids the need of a temporary variable!
    Object.assign(workingArray, {
      [m]: workingArray[i],
      [i]: workingArray[m]
    })
  }

  return workingArray
}

module.exports = {
  makeLoopingOrderedPlaylistPicker,
  makeNonLoopingOrderedPlaylistPicker,
  makeLoopingShufflePlaylistPicker,
  makeNonLoopingShufflePlaylistPicker,

  byName: {
    'order':           makeNonLoopingOrderedPlaylistPicker,
    'ordered':         makeNonLoopingOrderedPlaylistPicker,
    'order-loop':      makeLoopingOrderedPlaylistPicker,
    'ordered-loop':    makeLoopingOrderedPlaylistPicker,
    'order-noloop':    makeNonLoopingOrderedPlaylistPicker,
    'ordered-noloop':  makeNonLoopingOrderedPlaylistPicker,
    'order-no-loop':   makeNonLoopingOrderedPlaylistPicker,
    'ordered-no-loop': makeNonLoopingOrderedPlaylistPicker,
    'shuffle':         makeLoopingShufflePlaylistPicker,
    'shuffle-loop':    makeLoopingShufflePlaylistPicker,
    'shuffle-noloop':  makeNonLoopingShufflePlaylistPicker,
    'shuffle-no-loop': makeNonLoopingShufflePlaylistPicker,
  }
}