summaryrefslogtreecommitdiff
path: root/client/lib/util.js
blob: fd487686f0f200cd47a00152f5615d44b9560a10 (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
import Tone from 'tone'
import StartAudioContext from './startAudioContext'

const isIphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))
const isIpad = (navigator.userAgent.match(/iPad/i))
const isAndroid = (navigator.userAgent.match(/Android/i))
const isMobile = isIphone || isIpad || isAndroid
const isDesktop = ! isMobile

document.body.classList.add(isMobile ? 'mobile' : 'desktop')

const browser = { isIphone, isIpad, isAndroid, isMobile, isDesktop }

function clamp(n,a,b){ return n<a?a:n<b?n:b }
function choice (a){ return a[ Math.floor(Math.random() * a.length) ] }
function mod(n,m){ return n-(m * Math.floor(n/m)) }
function randint(n){ return (Math.random()*n)|0 }
function randrange(a,b){ return a + Math.random() * (b-a) }
function randsign(){ return Math.random() >= 0.5 ? -1 : 1 }
function lerp(n,a,b){ return (b-a)*n+a }
function angle(x0,y0,x1,y1){ return Math.atan2(y1-y0,x1-x0) }
function dist(x0,y0,x1,y1){ return Math.sqrt(Math.pow(x1-x0,2)+Math.pow(y1-y0,2)) }
function xor(a,b){ a=!!a; b=!!b; return (a||b) && !(a&&b) }
function shuffle(a){
  for (var i = a.length; i > 0; i--){
    var r = randint(i)
    var swap = a[i-1]
    a[i-1] = a[r]
    a[r] = swap
  }
  return a
}
// returns a gaussian random function with the given mean and stdev.
function gaussian(mean, stdev) {
  let y2;
  let use_last = false;
  return () => {
    let y1;
    if (use_last) {
      y1 = y2;
      use_last = false;
    }
    else {
      let x1, x2, w;
      do {
        x1 = 2.0 * Math.random() - 1.0;
        x2 = 2.0 * Math.random() - 1.0;
        w  = x1 * x1 + x2 * x2;               
      } while( w >= 1.0);
      w = Math.sqrt((-2.0 * Math.log(w))/w);
      y1 = x1 * w;
      y2 = x2 * w;
      use_last = true;
    }

    let retval = mean + stdev * y1;
    if (retval > 0) 
      return retval;
    return -retval;
  }
}

function requestAudioContext (fn) {
	if (isMobile) {
    const container = document.createElement('div')
    const button = document.createElement('div')
    button.innerHTML = 'Tap to start - please unmute your phone'
    Object.assign(container.style, {
			display: 'block',
      position: 'absolute',
      width: '100%',
      height: '100%',
      zIndex: '10000',
      top: '0px',
      left: '0px',
      backgroundColor: 'rgba(0, 0, 0, 0.8)',
    })
		Object.assign(button.style, {
			display: 'block',
		  position: 'absolute',
		  left: '50%',
		  top: '50%',
			padding: '20px',
		  backgroundColor: '#7F33ED',
		  color: 'white',
		  fontFamily: 'monospace',
		  borderRadius: '3px',
		  transform: 'translate3D(-50%,-50%,0)',
		  textAlign: 'center',
			lineHeight: '1.5',
			width: '150px',
    })
    container.appendChild(button)
    document.body.appendChild(container)
    StartAudioContext.setContext(Tone.context)
    StartAudioContext.on(button)
    StartAudioContext.onStarted(_ => {
      container.remove()
			fn()
  	})
	} else {
		fn()
	}
}

export {
  clamp, choice, mod, lerp, angle, dist, xor,
  randint, randrange, randsign, shuffle, gaussian,
  browser, requestAudioContext,
}