<commit_before>Array.prototype.peek = function () {
  if (this.length < 1) {
    return undefined
  }
  return this[this.length - 1]
}

var Pins = (function () {
'use strict';

var $ = window.jQuery
  , my = {}
  , pins = []
  , last = []
  , hidden = []
  , picked = []
  , bowled = 0

function countVisible() {
  var count = 0
    , i = 0

  for (i = 0; i < 10; i += 1) {
    if (!hidden[i]) {
      count += 1
    }
  }

  return count
}

function getAdjacent (value) {
  switch (value) {
    case 0: return [1, 4]
    case 1: return [0, 2, 4, 5]
    case 2: return [1, 3, 5, 6]
    case 3: return [2, 6]
    case 4: return [0, 1, 5, 7]
    case 5: return [1, 2, 4, 6, 7, 8]
    case 6: return [2, 3, 5, 8]
    case 7: return [4, 5, 8, 9]
    case 8: return [5, 6, 7, 9]
    case 9: return [7, 8]
    default: return []
  }
}

function isAdjacent (a, b) {
  return getAdjacent(a).indexOf(b) > -1
}

function anyAdjacent (a, b) {
  var i = 0
    , j = 0
  for (i = 0; i < a.length; i += 1) {
    for (j = 0; j < b.length; j += 1) {
      if (isAdjacent(a[i], b[j])) {
        return true
      }
    }
  }
  return false
}

function isAllowed (values, allowed) {
  var value = parseInt(values.sort().join(''), 10)
  return allowed.indexOf(value) > -1
}

function isValid (values) {
  var i = 0

  for (i = 0; i < values.length; i += 1) {
    if (hidden[values[i]]) {
      return false
    }
  }

  if (countVisible() >= 10) {
    switch (values.length) {
      case 0: return true
      case 1: return isAllowed(values, [4,6,7,8,9])
      case 2: return isAllowed(values, [47,68,78,79,89])
      case 3: return isAllowed(values, [478,479,678,689,789])
      default: return false
    }
  }

  if (last.length > 0 && values.length > 0) {
    if (!anyAdjacent(values, last)) {
      return false
    }
  }

  switch (values.length) {
    case 0: return true
    case 1: return isAllowed(values, [0,1,2,3,4,5,6,7,8,9])
    case 2: return isAllowed(values, [1,4,12,14,15,23,25,26,36,45,47,56,57,58,68,78,79,89])
    case 3: return isAllowed(values, [12,14,15,45,47,123,124,125,126,145,147,156,157,158,235,236,245,256,257,258,268,356,368,456,457,458,478,479,567,568,578,579,589,678,689,789])
    default: return false
  }
}

function getScore (values) {
  var score = 0
    , pin = null
    , i = 0
  if (values.length <= 0) {
    return undefined
  }
  for (i = 0; i < values.length; i += 1) {
    if (!hidden[values[i]]) {
      score += $('#pin'+values[i]).int()
    }
  }
  score = parseInt(('' + score).split('').peek(), 10)
  return score
}

function canSelect (value) {
  var values = pins.slice()
  values.push(value)
  return isValid(values)
}

function canUnselect (value) {
  var values = pins.slice()
    , index = values.indexOf(value)
  if (index > -1) {
    values.splice(index, 1)
    return isValid(values)
  }
  return false
}

function canScore (ball) {
  var i = 0
    , j = 0
    , k = 0
  if (ball === undefined) {
    return false
  }
  for (i = 0; i < 10; i += 1) {
    if (isValid([i]) && getScore([i]) === ball) {
      console.log('score with: '+[i]+' ball: '+ball)
      return true
    }
    for (j = 0; j < 10; j += 1) {
      if (isValid([i,j]) && getScore([i,j]) === ball) {
        console.log('score with: '+[i,j]+' ball: '+ball)
        return true
      }
      for (k = 0; k < 10; k += 1) {
        if (isValid([i,j,k]) && getScore([i,j,k]) === ball) {
          console.log('score with: '+[i,j,k]+' ball: '+ball)
          return true
        }
      }
    }
  }
  return false
}

function pinCenter () {
  var x = 0
    , y = 0
    , i = 0
    , c = null

  if (pins.length > 0) {
    for (i = 0; i < pins.length; i += 1) {
      c = $('#pin'+pins[i]).center()
      x += c.x
      y += c.y
    }
    x = (x / pins.length) - 2.6
    y = (y / pins.length) - 2.6
    return { x: x, y: y }
  }
  return undefined
}

my.reset = function (all) {
  var i = 0
  if (all !== true) {
    for (i = 0; i < pins.length; i += 1) {
      picked[pins[i]] = false
      hidden[pins[i]] = false
    }
  } else {
    for (i = 0; i < 10; i += 1) {
      picked[i] = false
      hidden[i] = false
    }
  }
  pins = []
  last = []
  bowled = 0
}

my.render = function () {
  var pin = null
    , i = 0

  for (i = 0; i < 10; i += 1) {
    pin = $('#pin'+i)
    if (hidden[i]) {
      pin.add('hidden')
    } else {
      pin.remove('hidden')
    }
    if (picked[i]) {
      pin.add('picked')
    } else {
      pin.remove('picked')
    }
  }
}

my.select = function (value) {
  if (canSelect(value)) {
    pins.push(value)
    picked[value] = true
  }
}

my.unselect = function (value) {
  if (canUnselect(value)) {
    pins.splice(pins.indexOf(value), 1)
    picked[value] = false
  }
}

my.toggle = function (value) {
  if (picked[value]) {
    this.unselect(value)
  } else {
    this.select(value)
  }
}

my.playable = function (ball1, ball2, ball3) {
  if (countVisible() <= 0) {
    return false
  }
  return canScore(ball1) || canScore(ball2) || canScore(ball3)
}

my.bowl = function () {
  var i = 0

  for (i = 0; i < pins.length; i += 1) {
    hidden[pins[i]] = true
  }

  bowled += pins.length
  last = pins
  pins = []
}

my.down = function () {
  return bowled
}

my.total = function () {
  return getScore(pins)
}

my.empty = function () {
  return countVisible() <= 0
}

return my
}())

var Scoreboard = (function () {
'use strict';

var $ = window.jQuery
  , s = {}
  , balls = []
  , scores = []
  , frames = []
  , frame = 1

function score (turn) {
  var sum = 0
    , t = 0
    , i = 0

  for (t = 1; t <= turn; t += 1) {
    if (balls[i] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+1] + balls[i+2]
        scores[t] = sum
      }
      i += 1
    } else if (balls[i] + balls[i+1] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+2]
        scores[t] = sum
      }
      i += 2
    } else {
      if (balls.length > i+1) {
        sum += balls[i] + balls[i+1]
        scores[t] = sum
      }
      i += 2
    }
  }
}

s.reset = function () {
  balls = []
  scores = []
  frames = []
  frame = 1
}

s.render = function () {
  var i = 0
    , html = ''
    , offset = $('#frame'+frame).center().y - 0.6

  for (i = 1; i < 11; i += 1) {
    html = scores[i] !== undefined ? scores[i] : ''
    $('#score'+i).html(html)
  }

  for (i = 1; i < 22; i += 1) {
    html = frames[i] !== undefined ? frames[i] : ''
    $('#frame'+i).html(html)
  }

  $('#marker').top(offset)
}

s.over = function () {
  return scores[10] !== undefined
}

s.skippable = function () {
  return frame % 2 === 1 && frame < 21
}

s.record = function (value) {
  if (value === undefined) {
    return
  }

  if (this.over()) {
    return
  }

  frames[frame] = value
  if (value === 10) {
    frames[frame] = 'X'
  }
  if (frame % 2 === 0 && value + balls[balls.length - 1] === 10) {
    frames[frame] = '/'
  }
  balls.push(value)
  score(Math.ceil(frame / 2))

  if (value === 10 && frame % 2 === 1 && frame < 19) {
    frame += 1
  }
  frame += 1
}

return s
}())

;(function (Spare) {
'use strict';

var $ = window.jQuery
  , chute0 = []
  , chute1 = []
  , chute2 = []

function shuffle (array) {
  var i = 0
    , j = 0
    , temp = null

  for (i = array.length - 1; i > 0; i -= 1) {
    j = Math.floor(Math.random() * (i + 1))
    temp = array[i]
    array[i] = array[j]
    array[j] = temp
  }
}

function drawSkip () {
  if (Scoreboard.over()) {
    $('#skip').html('New Game')
  } else {
    $('#skip').html('Next Ball')
  }
}

function drawChute (selector, count) {
  var i = 0
    , html = ''

  for (i = 0; i < count; i += 1) {
    html += '◉ '
  }
  for (i = i; i < 5; i += 1) {
    html += '◎ '
  }
  $(selector).html(html)
}

function drawBall (index, values) {
  if (values.length > 0) {
    $('#ball'+index).html(values[values.length - 1])
  } else {
    $('#ball'+index).add('hidden')
  }
  drawChute('#chute'+index, values.length)
}

function resetBall (index, values) {
  $('#ball'+index).remove('hidden')
  drawBall(index, values)
}

function resetLane() {
  var values = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]
    , i = 0

  Pins.reset(true)

  if (!Scoreboard.over()) {
    do {
      shuffle(values)
      for (i = 0; i < 10; i += 1) {
        $('#pin'+i).html(values[i]).data(i)
      }
      chute0 = values.slice(10, 15)
      chute1 = values.slice(15, 18)
      chute2 = values.slice(18, 20)
    } while (!Pins.playable(chute0.peek(), chute1.peek(), chute2.peek()))
  } else {
    for (i = 0; i < 10; i += 1) {
      $('#pin'+i).add('hidden')
    }
    chute0 = []
    chute1 = []
    chute2 = []
  }

  resetBall(0, chute0)
  resetBall(1, chute1)
  resetBall(2, chute2)

  console.log('lane reset')
}

function reset () {
  Scoreboard.reset()
  drawSkip()
  resetLane()
}

function onPin (event) {
  var target = $(event.srcElement || event.target)
  Pins.toggle(target.data())
}

function nextBall () {
  if (!Scoreboard.over()) {
    Scoreboard.record(Pins.down())
    chute0.pop()
    chute1.pop()
    chute2.pop()
    drawBall(0, chute0)
    drawBall(1, chute1)
    drawBall(2, chute2)
  } else {
    reset()
  }
}

function onSkip () {
  if (Scoreboard.skippable()) {
    nextBall()
    Pins.reset()
  } else {
    nextBall()
    resetLane()
  }
  drawSkip()
}

function onBall (event) {
  var target = $(event.srcElement || event.target)
    , total = Pins.total()

  if (target.unwrap().id === 'ball0') {
    if (total === chute0.peek()) {
      chute0.pop()
      drawBall(0, chute0)
      Pins.bowl()
    }
  }
  if (target.unwrap().id === 'ball1') {
    if (total === chute1.peek()) {
      chute1.pop()
      drawBall(1, chute1)
      Pins.bowl()
    }
  }
  if (target.unwrap().id === 'ball2') {
    if (total === chute2.peek()) {
      chute2.pop()
      drawBall(2, chute2)
      Pins.bowl()
    }
  }
  if (Pins.empty()) {
    nextBall()
    resetLane()
  }
  drawSkip()
}

function render (time) {
  requestAnimationFrame(render)
  Pins.render()
  Scoreboard.render()
}

Spare.play = function () {
  var i = 0

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).touch(onPin, null)
  }
  for (i = 0; i < 3; i += 1) {
    $('#ball'+i).touch(onBall, null)
  }
  $('#skip').touch(onSkip, null)
  reset()
  requestAnimationFrame(render)
}

})(window.Spare = window.Spare || {})
<commit_msg>Hides all the pins once the game's over.<commit_after>Array.prototype.peek = function () {
  if (this.length < 1) {
    return undefined
  }
  return this[this.length - 1]
}

var Pins = (function () {
'use strict';

var $ = window.jQuery
  , my = {}
  , pins = []
  , last = []
  , hidden = []
  , picked = []
  , bowled = 0

function countVisible() {
  var count = 0
    , i = 0

  for (i = 0; i < 10; i += 1) {
    if (!hidden[i]) {
      count += 1
    }
  }

  return count
}

function getAdjacent (value) {
  switch (value) {
    case 0: return [1, 4]
    case 1: return [0, 2, 4, 5]
    case 2: return [1, 3, 5, 6]
    case 3: return [2, 6]
    case 4: return [0, 1, 5, 7]
    case 5: return [1, 2, 4, 6, 7, 8]
    case 6: return [2, 3, 5, 8]
    case 7: return [4, 5, 8, 9]
    case 8: return [5, 6, 7, 9]
    case 9: return [7, 8]
    default: return []
  }
}

function isAdjacent (a, b) {
  return getAdjacent(a).indexOf(b) > -1
}

function anyAdjacent (a, b) {
  var i = 0
    , j = 0
  for (i = 0; i < a.length; i += 1) {
    for (j = 0; j < b.length; j += 1) {
      if (isAdjacent(a[i], b[j])) {
        return true
      }
    }
  }
  return false
}

function isAllowed (values, allowed) {
  var value = parseInt(values.sort().join(''), 10)
  return allowed.indexOf(value) > -1
}

function isValid (values) {
  var i = 0

  for (i = 0; i < values.length; i += 1) {
    if (hidden[values[i]]) {
      return false
    }
  }

  if (countVisible() >= 10) {
    switch (values.length) {
      case 0: return true
      case 1: return isAllowed(values, [4,6,7,8,9])
      case 2: return isAllowed(values, [47,68,78,79,89])
      case 3: return isAllowed(values, [478,479,678,689,789])
      default: return false
    }
  }

  if (last.length > 0 && values.length > 0) {
    if (!anyAdjacent(values, last)) {
      return false
    }
  }

  switch (values.length) {
    case 0: return true
    case 1: return isAllowed(values, [0,1,2,3,4,5,6,7,8,9])
    case 2: return isAllowed(values, [1,4,12,14,15,23,25,26,36,45,47,56,57,58,68,78,79,89])
    case 3: return isAllowed(values, [12,14,15,45,47,123,124,125,126,145,147,156,157,158,235,236,245,256,257,258,268,356,368,456,457,458,478,479,567,568,578,579,589,678,689,789])
    default: return false
  }
}

function getScore (values) {
  var score = 0
    , pin = null
    , i = 0
  if (values.length <= 0) {
    return undefined
  }
  for (i = 0; i < values.length; i += 1) {
    if (!hidden[values[i]]) {
      score += $('#pin'+values[i]).int()
    }
  }
  score = parseInt(('' + score).split('').peek(), 10)
  return score
}

function canSelect (value) {
  var values = pins.slice()
  values.push(value)
  return isValid(values)
}

function canUnselect (value) {
  var values = pins.slice()
    , index = values.indexOf(value)
  if (index > -1) {
    values.splice(index, 1)
    return isValid(values)
  }
  return false
}

function canScore (ball) {
  var i = 0
    , j = 0
    , k = 0
  if (ball === undefined) {
    return false
  }
  for (i = 0; i < 10; i += 1) {
    if (isValid([i]) && getScore([i]) === ball) {
      console.log('score with: '+[i]+' ball: '+ball)
      return true
    }
    for (j = 0; j < 10; j += 1) {
      if (isValid([i,j]) && getScore([i,j]) === ball) {
        console.log('score with: '+[i,j]+' ball: '+ball)
        return true
      }
      for (k = 0; k < 10; k += 1) {
        if (isValid([i,j,k]) && getScore([i,j,k]) === ball) {
          console.log('score with: '+[i,j,k]+' ball: '+ball)
          return true
        }
      }
    }
  }
  return false
}

function pinCenter () {
  var x = 0
    , y = 0
    , i = 0
    , c = null

  if (pins.length > 0) {
    for (i = 0; i < pins.length; i += 1) {
      c = $('#pin'+pins[i]).center()
      x += c.x
      y += c.y
    }
    x = (x / pins.length) - 2.6
    y = (y / pins.length) - 2.6
    return { x: x, y: y }
  }
  return undefined
}

my.reset = function (all) {
  var i = 0
  if (all !== true) {
    for (i = 0; i < pins.length; i += 1) {
      picked[pins[i]] = false
      hidden[pins[i]] = false
    }
  } else {
    for (i = 0; i < 10; i += 1) {
      picked[i] = false
      hidden[i] = false
    }
  }
  pins = []
  last = []
  bowled = 0
}

my.hide = function () {
  var i = 0
  for (i = 0; i < 10; i += 1) {
    hidden[i] = true
  }
}

my.render = function () {
  var pin = null
    , i = 0

  for (i = 0; i < 10; i += 1) {
    pin = $('#pin'+i)
    if (hidden[i]) {
      pin.add('hidden')
    } else {
      pin.remove('hidden')
    }
    if (picked[i]) {
      pin.add('picked')
    } else {
      pin.remove('picked')
    }
  }
}

my.select = function (value) {
  if (canSelect(value)) {
    pins.push(value)
    picked[value] = true
  }
}

my.unselect = function (value) {
  if (canUnselect(value)) {
    pins.splice(pins.indexOf(value), 1)
    picked[value] = false
  }
}

my.toggle = function (value) {
  if (picked[value]) {
    this.unselect(value)
  } else {
    this.select(value)
  }
}

my.playable = function (ball1, ball2, ball3) {
  if (countVisible() <= 0) {
    return false
  }
  return canScore(ball1) || canScore(ball2) || canScore(ball3)
}

my.bowl = function () {
  var i = 0

  for (i = 0; i < pins.length; i += 1) {
    hidden[pins[i]] = true
  }

  bowled += pins.length
  last = pins
  pins = []
}

my.down = function () {
  return bowled
}

my.total = function () {
  return getScore(pins)
}

my.empty = function () {
  return countVisible() <= 0
}

return my
}())

var Scoreboard = (function () {
'use strict';

var $ = window.jQuery
  , s = {}
  , balls = []
  , scores = []
  , frames = []
  , frame = 1

function score (turn) {
  var sum = 0
    , t = 0
    , i = 0

  for (t = 1; t <= turn; t += 1) {
    if (balls[i] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+1] + balls[i+2]
        scores[t] = sum
      }
      i += 1
    } else if (balls[i] + balls[i+1] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+2]
        scores[t] = sum
      }
      i += 2
    } else {
      if (balls.length > i+1) {
        sum += balls[i] + balls[i+1]
        scores[t] = sum
      }
      i += 2
    }
  }
}

s.reset = function () {
  balls = []
  scores = []
  frames = []
  frame = 1
}

s.render = function () {
  var i = 0
    , html = ''
    , offset = $('#frame'+frame).center().y - 0.6

  for (i = 1; i < 11; i += 1) {
    html = scores[i] !== undefined ? scores[i] : ''
    $('#score'+i).html(html)
  }

  for (i = 1; i < 22; i += 1) {
    html = frames[i] !== undefined ? frames[i] : ''
    $('#frame'+i).html(html)
  }

  $('#marker').top(offset)
}

s.over = function () {
  return scores[10] !== undefined
}

s.skippable = function () {
  return frame % 2 === 1 && frame < 21
}

s.record = function (value) {
  if (value === undefined) {
    return
  }

  if (this.over()) {
    return
  }

  frames[frame] = value
  if (value === 10) {
    frames[frame] = 'X'
  }
  if (frame % 2 === 0 && value + balls[balls.length - 1] === 10) {
    frames[frame] = '/'
  }
  balls.push(value)
  score(Math.ceil(frame / 2))

  if (value === 10 && frame % 2 === 1 && frame < 19) {
    frame += 1
  }
  frame += 1
}

return s
}())

;(function (Spare) {
'use strict';

var $ = window.jQuery
  , chute0 = []
  , chute1 = []
  , chute2 = []

function shuffle (array) {
  var i = 0
    , j = 0
    , temp = null

  for (i = array.length - 1; i > 0; i -= 1) {
    j = Math.floor(Math.random() * (i + 1))
    temp = array[i]
    array[i] = array[j]
    array[j] = temp
  }
}

function drawSkip () {
  if (Scoreboard.over()) {
    $('#skip').html('New Game')
  } else {
    $('#skip').html('Next Ball')
  }
}

function drawChute (selector, count) {
  var i = 0
    , html = ''

  for (i = 0; i < count; i += 1) {
    html += '◉ '
  }
  for (i = i; i < 5; i += 1) {
    html += '◎ '
  }
  $(selector).html(html)
}

function drawBall (index, values) {
  if (values.length > 0) {
    $('#ball'+index).html(values[values.length - 1])
  } else {
    $('#ball'+index).add('hidden')
  }
  drawChute('#chute'+index, values.length)
}

function resetBall (index, values) {
  $('#ball'+index).remove('hidden')
  drawBall(index, values)
}

function resetLane() {
  var values = [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9]
    , i = 0

  Pins.reset(true)

  if (!Scoreboard.over()) {
    do {
      shuffle(values)
      for (i = 0; i < 10; i += 1) {
        $('#pin'+i).html(values[i]).data(i)
      }
      chute0 = values.slice(10, 15)
      chute1 = values.slice(15, 18)
      chute2 = values.slice(18, 20)
    } while (!Pins.playable(chute0.peek(), chute1.peek(), chute2.peek()))
  } else {
    Pins.hide()
    chute0 = []
    chute1 = []
    chute2 = []
  }

  resetBall(0, chute0)
  resetBall(1, chute1)
  resetBall(2, chute2)

  console.log('lane reset')
}

function reset () {
  Scoreboard.reset()
  drawSkip()
  resetLane()
}

function onPin (event) {
  var target = $(event.srcElement || event.target)
  Pins.toggle(target.data())
}

function nextBall () {
  if (!Scoreboard.over()) {
    Scoreboard.record(Pins.down())
    chute0.pop()
    chute1.pop()
    chute2.pop()
    drawBall(0, chute0)
    drawBall(1, chute1)
    drawBall(2, chute2)
  } else {
    reset()
  }
}

function onSkip () {
  if (Scoreboard.skippable()) {
    nextBall()
    Pins.reset()
  } else {
    nextBall()
    resetLane()
  }
  drawSkip()
}

function onBall (event) {
  var target = $(event.srcElement || event.target)
    , total = Pins.total()

  if (target.unwrap().id === 'ball0') {
    if (total === chute0.peek()) {
      chute0.pop()
      drawBall(0, chute0)
      Pins.bowl()
    }
  }
  if (target.unwrap().id === 'ball1') {
    if (total === chute1.peek()) {
      chute1.pop()
      drawBall(1, chute1)
      Pins.bowl()
    }
  }
  if (target.unwrap().id === 'ball2') {
    if (total === chute2.peek()) {
      chute2.pop()
      drawBall(2, chute2)
      Pins.bowl()
    }
  }
  if (Pins.empty()) {
    nextBall()
    resetLane()
  }
  drawSkip()
}

function render (time) {
  requestAnimationFrame(render)
  Pins.render()
  Scoreboard.render()
}

Spare.play = function () {
  var i = 0

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).touch(onPin, null)
  }
  for (i = 0; i < 3; i += 1) {
    $('#ball'+i).touch(onBall, null)
  }
  $('#skip').touch(onSkip, null)
  reset()
  requestAnimationFrame(render)
}

})(window.Spare = window.Spare || {})
<|endoftext|>


<commit_before>Array.prototype.peek = function () {
  if (this.length < 1) {
    return undefined
  }
  return this[this.length - 1]
}

var Pins = (function () {
'use strict';

var $ = window.jQuery
  , my = {}
  , pins = []
  , last = []
  , bowled = 0

function countVisible() {
  var count = 0
    , i = 0
  for (i = 0; i < 10; i += 1) {
    if (!$('#pin'+i).has('hidden')) {
      count += 1
    }
  }
  return count
}

function getAdjacent (value) {
  switch (value) {
    case 0: return [1, 4]
    case 1: return [0, 2, 4, 5]
    case 2: return [1, 3, 5, 6]
    case 3: return [2, 6]
    case 4: return [0, 1, 5, 7]
    case 5: return [1, 2, 4, 6, 7, 8]
    case 6: return [2, 3, 5, 8]
    case 7: return [4, 5, 8, 9]
    case 8: return [5, 6, 7, 9]
    case 9: return [7, 8]
    default: return []
  }
}

function isAdjacent (a, b) {
  return getAdjacent(a).indexOf(b) > -1
}

function anyAdjacent (a, b) {
  var i = 0
    , j = 0
  for (i = 0; i < a.length; i += 1) {
    for (j = 0; j < b.length; j += 1) {
      if (isAdjacent(a[i], b[j])) {
        return true
      }
    }
  }
  return false
}

function isAllowed (values, allowed) {
  var value = parseInt(values.sort().join(''), 10)
  return allowed.indexOf(value) > -1
}

function isValid (values) {
  var i = 0
  if (countVisible() >= 10) {
    switch (values.length) {
      case 0: return true
      case 1: return isAllowed(values, [4,6,7,8,9])
      case 2: return isAllowed(values, [47,68,78,79,89])
      case 3: return isAllowed(values, [478,479,678,689,789])
      default: return false
    }
  }

  if (last.length > 0 && values.length > 0) {
    if (!anyAdjacent(values, last)) {
      return false
    }
  }

  switch (values.length) {
    case 0: return true
    case 1: return isAllowed(values, [0,1,2,3,4,5,6,7,8,9])
    case 2: return isAllowed(values, [1,4,12,14,15,23,25,26,36,45,47,56,57,58,68,78,79,89])
    case 3: return isAllowed(values, [12,14,15,45,47,123,124,125,126,145,147,156,157,158,235,236,245,256,257,258,268,356,368,456,457,458,478,479,567,568,578,579,589,678,689,789])
    default: return false
  }
}

function canSelect (value) {
  var values = pins.slice()
  values.push(value)
  return isValid(values)
}

function canUnselect (value) {
  var values = pins.slice()
    , index = values.indexOf(value)
  if (index > -1) {
    values.splice(index, 1)
    return isValid(values)
  }
  return false
}

my.reset = function () {
  var i = 0
  for (i = 0; i < pins.length; i += 1) {
    $('#pin'+pins[i]).remove('picked')
  }
  pins = []
  last = []
  bowled = 0
}

my.select = function (value) {
  if (canSelect(value)) {
    pins.push(value)
    $('#pin'+value).toggle('picked')
  }
}

my.unselect = function (value) {
  if (canUnselect(value)) {
    pins.splice(pins.indexOf(value), 1)
    $('#pin'+value).toggle('picked')
  }
}

my.empty = function () {
  return countVisible() <= 0
}

my.bowl = function () {
  var i = 0
  for (i = 0; i < pins.length; i += 1) {
    $('#pin'+pins[i]).add('hidden')
  }
  bowled += pins.length
  last = pins
  pins = []
}

my.down = function () {
  return bowled
}

my.total = function () {
  var score = 0
    , i = 0
  for (i = 0; i < pins.length; i += 1) {
    score += $('#pin'+pins[i]).int()
  }
  score = parseInt(('' + score).split('').peek(), 10)
  return score
}

return my
}())

;(function (Spare) {
'use strict';

var $ = window.jQuery
  , doc = $(document)
  , balls = []
  , pins = []
  , last = []
  , chute0 = []
  , chute1 = []
  , chute2 = []
  , frame = 1

function shuffle (array) {
  var i = 0
    , j = 0
    , temp = null

  for (i = array.length - 1; i > 0; i -= 1) {
    j = Math.floor(Math.random() * (i + 1))
    temp = array[i]
    array[i] = array[j]
    array[j] = temp
  }
}

function drawChute (selector, count) {
  var i = 0
    , html = ''

  for (i = 0; i < count; i += 1) {
    html += '◉ '
  }
  for (i = i; i < 5; i += 1) {
    html += '◎ '
  }
  $(selector).html(html)
}

function drawBall (index, values) {
  if (values.length > 0) {
    $('#ball'+index).html(values[values.length - 1])
  } else {
    $('#ball'+index).add('hidden')
  }
  drawChute('#chute'+index, values.length)
}

function resetBall (index, values) {
  $('#ball'+index).remove('hidden')
  drawBall(index, values)
}

function resetLane() {
  var i = 0
    , values = []

  for (i = 0; i < 10; i += 1) {
    values.push(i)
    values.push(i)
  }
  shuffle(values)

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).html(values[i]).data(i).remove('hidden')
  }

  chute0 = values.slice(10, 15)
  chute1 = values.slice(15, 18)
  chute2 = values.slice(18, 20)

  resetBall(0, chute0)
  resetBall(1, chute1)
  resetBall(2, chute2)
}

function resetGame () {
  var i = 0

  balls = []
  frame = 1

  for (i = 1; i <= 10; i += 1) {
    $('#score'+i).html('')
  }
  for (i = 1; i <= 21; i += 1) {
    $('#frame'+i).html('')
  }
}

function reset () {
  Pins.reset()
  resetGame()
  resetLane()
}

function score (turn) {
  var sum = 0
    , t = 0
    , i = 0

  for (t = 1; t <= turn; t += 1) {
    if (balls[i] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+1] + balls[i+2]
        $('#score'+t).html(sum)
      }
      i += 1
    } else if (balls[i] + balls[i+1] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+2]
        $('#score'+t).html(sum)
      }
      i += 2
    } else {
      if (balls.length > i+1) {
        sum += balls[i] + balls[i+1]
        $('#score'+t).html(sum)
      }
      i += 2
    }
  }
}

function bowl (value) {
  if (value === undefined) {
    return
  }

  if ($('#score10').html() !== '') {
    reset()
    return
  }

  $('#frame'+frame).html(value)
  if (value === 10) {
    $('#frame'+frame).html('X')
  }
  if (frame % 2 === 0 && value + balls[balls.length - 1] === 10) {
    $('#frame'+frame).html('/')
  }
  balls.push(value)
  score(Math.ceil(frame / 2))

  if (value === 10 && frame % 2 === 1 && frame < 19) {
    frame += 1
  }
  frame += 1
}

function onPin (event) {
  var target = $(event.srcElement || event.target)
  if (target.has('picked')) {
    Pins.unselect(target.data())
  } else {
    Pins.select(target.data())
  }
}

function rollBall () {
  Pins.bowl()
  if (Pins.empty()) {
    bowl(Pins.down())
    resetLane()
  }
}

function onBall (event) {
  var target = $(event.srcElement || event.target)
    , total = Pins.total()

  if (total !== chute0.peek() && total !== chute1.peek() && total !== chute2.peek()) {
    chute0.pop()
    chute1.pop()
    chute2.pop()
    drawBall(0, chute0)
    drawBall(1, chute1)
    drawBall(2, chute2)
    bowl(Pins.down())
    Pins.reset()
    return
  }

  if (target.unwrap().id === 'ball0') {
    if (total === chute0.peek()) {
      chute0.pop()
      drawBall(0, chute0)
      rollBall()
    }
  }
  if (target.unwrap().id === 'ball1') {
    if (total === chute1.peek()) {
      chute1.pop()
      drawBall(1, chute1)
      rollBall()
    }
  }
  if (target.unwrap().id === 'ball2') {
    if (total === chute2.peek()) {
      chute2.pop()
      drawBall(2, chute2)
      rollBall()
    }
  }
}

Spare.play = function () {
  var i = 0

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).touch(onPin, null)
  }
  for (i = 0; i < 3; i += 1) {
    $('#ball'+i).touch(onBall, null)
  }
  reset()
}

})(window.Spare = window.Spare || {})
<commit_msg>Solves for scorability so I can tell if the game should keep going.<commit_after>Array.prototype.peek = function () {
  if (this.length < 1) {
    return undefined
  }
  return this[this.length - 1]
}

var Pins = (function () {
'use strict';

var $ = window.jQuery
  , my = {}
  , pins = []
  , last = []
  , bowled = 0

function countVisible() {
  var count = 0
    , i = 0
  for (i = 0; i < 10; i += 1) {
    if (!$('#pin'+i).has('hidden')) {
      count += 1
    }
  }
  return count
}

function getAdjacent (value) {
  switch (value) {
    case 0: return [1, 4]
    case 1: return [0, 2, 4, 5]
    case 2: return [1, 3, 5, 6]
    case 3: return [2, 6]
    case 4: return [0, 1, 5, 7]
    case 5: return [1, 2, 4, 6, 7, 8]
    case 6: return [2, 3, 5, 8]
    case 7: return [4, 5, 8, 9]
    case 8: return [5, 6, 7, 9]
    case 9: return [7, 8]
    default: return []
  }
}

function isAdjacent (a, b) {
  return getAdjacent(a).indexOf(b) > -1
}

function anyAdjacent (a, b) {
  var i = 0
    , j = 0
  for (i = 0; i < a.length; i += 1) {
    for (j = 0; j < b.length; j += 1) {
      if (isAdjacent(a[i], b[j])) {
        return true
      }
    }
  }
  return false
}

function isAllowed (values, allowed) {
  var value = parseInt(values.sort().join(''), 10)
  return allowed.indexOf(value) > -1
}

function isValid (values) {
  var i = 0

  for (i = 0; i < values.length; i += 1) {
    if ($('#pin'+values[i]).has('hidden')) {
      return false
    }
  }

  if (countVisible() >= 10) {
    switch (values.length) {
      case 0: return true
      case 1: return isAllowed(values, [4,6,7,8,9])
      case 2: return isAllowed(values, [47,68,78,79,89])
      case 3: return isAllowed(values, [478,479,678,689,789])
      default: return false
    }
  }

  if (last.length > 0 && values.length > 0) {
    if (!anyAdjacent(values, last)) {
      return false
    }
  }

  switch (values.length) {
    case 0: return true
    case 1: return isAllowed(values, [0,1,2,3,4,5,6,7,8,9])
    case 2: return isAllowed(values, [1,4,12,14,15,23,25,26,36,45,47,56,57,58,68,78,79,89])
    case 3: return isAllowed(values, [12,14,15,45,47,123,124,125,126,145,147,156,157,158,235,236,245,256,257,258,268,356,368,456,457,458,478,479,567,568,578,579,589,678,689,789])
    default: return false
  }
}

function getScore (values) {
  var score = 0
    , pin = null
    , i = 0
  for (i = 0; i < values.length; i += 1) {
    pin = $('#pin'+values[i])
    if (!pin.has('hidden')) {
      score += pin.int()
    }
  }
  score = parseInt(('' + score).split('').peek(), 10)
  return score
}

function canSelect (value) {
  var values = pins.slice()
  values.push(value)
  return isValid(values)
}

function canUnselect (value) {
  var values = pins.slice()
    , index = values.indexOf(value)
  if (index > -1) {
    values.splice(index, 1)
    return isValid(values)
  }
  return false
}

function canScore (ball) {
  var i = 0
    , j = 0
    , k = 0
  if (ball === undefined) {
    return false
  }
  for (i = 0; i < 10; i += 1) {
    if (isValid([i]) && getScore([i]) === ball) {
      console.log('score with: '+[i]+' ball: '+ball)
      return true
    }
    for (j = 0; j < 10; j += 1) {
      if (isValid([i,j]) && getScore([i,j]) === ball) {
        console.log('score with: '+[i,j]+' ball: '+ball)
        return true
      }
      for (k = 0; k < 10; k += 1) {
        if (isValid([i,j,k]) && getScore([i,j,k]) === ball) {
          console.log('score with: '+[i,j,k]+' ball: '+ball)
          return true
        }
      }
    }
  }
  return false
}

my.reset = function (all) {
  var i = 0
  if (all !== true) {
    for (i = 0; i < pins.length; i += 1) {
      $('#pin'+pins[i]).remove('picked').remove('hidden')
    }
  } else {
    for (i = 0; i < 10; i += 1) {
      $('#pin'+i).remove('picked').remove('hidden')
    }
  }
  pins = []
  last = []
  bowled = 0
}

my.select = function (value) {
  if (canSelect(value)) {
    pins.push(value)
    $('#pin'+value).toggle('picked')
  }
}

my.unselect = function (value) {
  if (canUnselect(value)) {
    pins.splice(pins.indexOf(value), 1)
    $('#pin'+value).toggle('picked')
  }
}

my.scorable = function (ball1, ball2, ball3) {
  if (countVisible() <= 0) {
    console.log('score with: nothing')
    return true
  }
  return !canScore(ball1) && !canScore(ball2) && !canScore(ball3)
}

my.bowl = function () {
  var i = 0
  for (i = 0; i < pins.length; i += 1) {
    $('#pin'+pins[i]).add('hidden')
  }
  bowled += pins.length
  last = pins
  pins = []
}

my.down = function () {
  return bowled
}

my.total = function () {
  return getScore(pins)
}

return my
}())

;(function (Spare) {
'use strict';

var $ = window.jQuery
  , doc = $(document)
  , balls = []
  , chute0 = []
  , chute1 = []
  , chute2 = []
  , frame = 1

function shuffle (array) {
  var i = 0
    , j = 0
    , temp = null

  for (i = array.length - 1; i > 0; i -= 1) {
    j = Math.floor(Math.random() * (i + 1))
    temp = array[i]
    array[i] = array[j]
    array[j] = temp
  }
}

function drawChute (selector, count) {
  var i = 0
    , html = ''

  for (i = 0; i < count; i += 1) {
    html += '◉ '
  }
  for (i = i; i < 5; i += 1) {
    html += '◎ '
  }
  $(selector).html(html)
}

function drawBall (index, values) {
  if (values.length > 0) {
    $('#ball'+index).html(values[values.length - 1])
  } else {
    $('#ball'+index).add('hidden')
  }
  drawChute('#chute'+index, values.length)
}

function resetBall (index, values) {
  $('#ball'+index).remove('hidden')
  drawBall(index, values)
}

function resetLane() {
  var i = 0
    , values = []

  for (i = 0; i < 10; i += 1) {
    values.push(i)
    values.push(i)
  }
  shuffle(values)

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).html(values[i]).data(i)
  }

  chute0 = values.slice(10, 15)
  chute1 = values.slice(15, 18)
  chute2 = values.slice(18, 20)

  resetBall(0, chute0)
  resetBall(1, chute1)
  resetBall(2, chute2)

  console.log('lane reset')
}

function resetGame () {
  var i = 0

  balls = []
  frame = 1

  for (i = 1; i <= 10; i += 1) {
    $('#score'+i).html('')
  }
  for (i = 1; i <= 21; i += 1) {
    $('#frame'+i).html('')
  }
}

function reset () {
  Pins.reset(true)
  resetGame()
  resetLane()
}

function score (turn) {
  var sum = 0
    , t = 0
    , i = 0

  for (t = 1; t <= turn; t += 1) {
    if (balls[i] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+1] + balls[i+2]
        $('#score'+t).html(sum)
      }
      i += 1
    } else if (balls[i] + balls[i+1] === 10) {
      if (balls.length > i+2) {
        sum += 10 + balls[i+2]
        $('#score'+t).html(sum)
      }
      i += 2
    } else {
      if (balls.length > i+1) {
        sum += balls[i] + balls[i+1]
        $('#score'+t).html(sum)
      }
      i += 2
    }
  }
}

function bowl (value) {
  if (value === undefined) {
    return
  }

  if ($('#score10').html() !== '') {
    reset()
    return
  }

  $('#frame'+frame).html(value)
  if (value === 10) {
    $('#frame'+frame).html('X')
  }
  if (frame % 2 === 0 && value + balls[balls.length - 1] === 10) {
    $('#frame'+frame).html('/')
  }
  balls.push(value)
  score(Math.ceil(frame / 2))

  if (value === 10 && frame % 2 === 1 && frame < 19) {
    frame += 1
  }
  frame += 1
}

function onPin (event) {
  var target = $(event.srcElement || event.target)
  if (target.has('picked')) {
    Pins.unselect(target.data())
  } else {
    Pins.select(target.data())
  }
}

function rollBall () {
  Pins.bowl()
  while (Pins.scorable(chute0.peek(), chute1.peek(), chute2.peek())) {
    chute0.pop()
    chute1.pop()
    chute2.pop()
    drawBall(0, chute0)
    drawBall(1, chute1)
    drawBall(2, chute2)
    bowl(Pins.down())
    Pins.reset()
    if (chute0.length <= 0 && chute1.length <= 0 && chute2.length <= 0) {
      Pins.reset(true)
      resetLane()
      break
    }
  }
}

function onBall (event) {
  var target = $(event.srcElement || event.target)
    , total = Pins.total()

  if (target.unwrap().id === 'ball0') {
    if (total === chute0.peek()) {
      chute0.pop()
      drawBall(0, chute0)
      rollBall()
    }
  }
  if (target.unwrap().id === 'ball1') {
    if (total === chute1.peek()) {
      chute1.pop()
      drawBall(1, chute1)
      rollBall()
    }
  }
  if (target.unwrap().id === 'ball2') {
    if (total === chute2.peek()) {
      chute2.pop()
      drawBall(2, chute2)
      rollBall()
    }
  }
}

Spare.play = function () {
  var i = 0

  for (i = 0; i < 10; i += 1) {
    $('#pin'+i).touch(onPin, null)
  }
  for (i = 0; i < 3; i += 1) {
    $('#ball'+i).touch(onBall, null)
  }
  reset()
}

})(window.Spare = window.Spare || {})
<|endoftext|>


<commit_before>import React from "react";
import _ from "lodash";
// import {ReactSVGPanZoom} from 'react-svg-pan-zoom';
import * as globals from "./globals";
import graphUtil from "../util/graphUtil";

import Axes from "./graphAxes";
import Comments from "./graphComments";
import Participants from "./graphParticipants";
import Hulls from "./hull";
import BarChartsForGroupVotes from "./barChartsForGroupVotes";
import ExploreTid from "./exploreTid";
import TidCarousel from "./tidCarousel";
import Vote from "./voteView";

let ptptoiScaleFactor = 0.5;

class Graph extends React.Component {

  constructor(props) {
    super(props);
    this.Viewer = null;
    this.state = {
      selectedComment: null,
    };
  }

  componentWillMount() {
    console.log("graph mounted");
    document.getElementById("helpTextGroups").style.display = "none";
    document.getElementById("visualization_div").style.display = "none";
    document.getElementById("carouselPane").style.display = "none";
    document.getElementsByClassName("groupSelectionView")[0].style.display = "none";
  }

  handleCommentHover(selectedComment) {
    return () => {
      document.getElementById("readReactView").style.display = "none";
      this.setState({selectedComment});
    }
  }

  handleCommentClick(selectedComment) {
    return () => {
      document.getElementById("readReactView").style.display = "none";
      this.setState({selectedComment});
    }
  }

  handleReturnToVoteClicked() {
    document.getElementById("readReactView").style.display = "block";
    this.setState({selectedComment: null})
  }

  render() {

    if (!this.props.math) {
      return null;
    }

    let tidsToShowSet = _.keyBy(this.props.tidsToShow);

    let {
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCornerAssignments,
    } = graphUtil(this.props.comments, this.props.math, this.props.badTids);

    console.log(groupCornerAssignments);

    let should_only_show_voted_on_comments = false;

    commentsPoints = commentsPoints.filter((c) => {
      return !should_only_show_voted_on_comments || !_.isUndefined(tidsToShowSet[c.tid]);
    });
    let tidCarouselComments = this.props.comments.filter((c) => {
      return !should_only_show_voted_on_comments || !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let heading = (
 Opinion Graph

        This graph shows all people and all comments.

        Comments, identified by their number, are positioned more closely to comments that were voted on similarly (blue, in the correlation matrix above). Comments are positioned further away from comments that tended to be voted on differently (red, in the correlation matrix above).

People are positioned closer to the comments on which they agreed, and further from the comments on which they disagreed. Groups of participants that tended to vote similarly across many comments (elaborated in the previous section) are identified by their similar color.

);

    return (

        {this.props.renderHeading ? heading : ""}
        {
          this.state.selectedComment ?
          <ExploreTid
            handleReturnToVoteClicked={this.handleReturnToVoteClicked.bind(this)}
            selectedComment={this.state.selectedComment}
            votesByMe={this.props.votesByMe}
            onVoteClicked={this.props.onVoteClicked}
            comments={this.props.comment}/> :
          <Vote
            />
        }
        <TidCarousel
          commentsToShow={tidCarouselComments}
          handleCommentClick={this.handleCommentClick.bind(this)}
          />
        <svg width="100%" height={globals.side}>

          {/* Comment https://bl.ocks.org/mbostock/7555321 */}
          <g transform={`translate(${globals.side / 2}, ${15})`}>
            <text
              style={{
                fontFamily: "Georgia",
                fontSize: 14,
                fontStyle: "italic"
              }}
              textAnchor="middle">

            </text>
          </g>
          <Axes xCenter={xCenter} yCenter={yCenter} report={this.props.report}/>
          <Hulls hulls={hulls} showOnlyGroup={this.props.showOnlyGroup} />
          <Participants points={baseClustersScaled} ptptois={this.props.ptptois} ptptoiScaleFactor={ptptoiScaleFactor}/>
          <Comments
            commentsPoints={commentsPoints}
            selectedComment={this.state.selectedComment}
            handleCommentHover={this.handleCommentHover.bind(this)}
            points={commentsPoints}
            repfulAgreeTidsByGroup={this.props.repfulAgreeTidsByGroup}
            repfulDisageeTidsByGroup={this.props.repfulDisageeTidsByGroup}
            showOnlyGroup={this.props.showOnlyGroup}
            xx={xx}
            yy={yy}
            xCenter={xCenter}
            yCenter={yCenter}
            xScaleup={commentScaleupFactorX}
            yScaleup={commentScaleupFactorY}
            formatTid={this.props.formatTid}/>
          <BarChartsForGroupVotes
            selectedComment={this.state.selectedComment}
            allComments={this.props.comments}
            groups={window.preload.firstMath["group-votes"]}
            groupCornerAssignments={groupCornerAssignments}
            />
        </svg>

    );
  }
}

export default Graph;

          // <defs>
          //   <marker
          //     className={'helpArrow'}
          //     id={'ArrowTip'}
          //     viewBox={'0 0 14 14'}
          //     refX={'1'
          //     refY={'5'}
          //     markerWidth={'5'}
          //     markerHeight={'5'}
          //     orient={'auto'}>
          //     // "<path d='M 0 0 L 10 5 L 0 10 z' />
          //     <circle cx = {'6'} cy = {'6'} r = {'5'} />
          //   </marker>
          //   <clipPath id={"clipCircleVis2"}>
          //     <circle r={ptptOiRadius * ptptoiScaleFactor} cx={0} cy={0}/>
          //   </clipPath>
          //   <filter id={'colorMeMatrix'}>
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'0.33 0.33 0.33 0 0
          //       0.33 0.33 0.33 0 0
          //       0.33 0.33 0.33 0 0
          //       0 0 0 1 0'} />
          //   </filter>

          //   <filter id={'colorMeMatrixRed'}
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'1.00 0.60 0.60 0 0.3
          //         0.10 0.20 0.10 0 0
          //         0.10 0.10 0.20 0 0
          //         0 0 0 1 0'} />
          //   </filter>

          //   <filter id={'colorMeMatrixGreen'}>
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'0.20 0.10 0.10 0 0
          //         0.60 1.00 0.60 0 0.3
          //         0.10 0.10 0.40 0 0
          //         0 0 0 1 0'} />
          //   </filter>
          // </defs>

// {/* this.props.math["group-clusters"].map((cluster, i) => {
//   return (<text x={300} y={300}> Renzi Supporters </text>)
// }) : null */}

// componentDidMount() {
//   this.Viewer.fitToViewer();
// }
//

//   <button onClick={event => this.Viewer.zoomOnViewerCenter(1.1)}>Zoom in</button>
//   <button onClick={event => this.Viewer.fitSelection(40, 40, 200, 200)}>Zoom area</button>
//   <button onClick={event => this.Viewer.fitToViewer()}>Fit</button>
//

// <ReactSVGPanZoom
//   style={{outline: "1px solid black", fill: "white"}}
//   width={500} height={500} ref={Viewer => this.Viewer = Viewer}
//   onClick={event => console.log('click', event.x, event.y, event.originalEvent)}
//   onMouseMove={event => console.log('move', event.x, event.y)} >
//
// </ReactSVGPanZoom>
<commit_msg>keep hull elems in graph state using react refs<commit_after>import React from "react";
import _ from "lodash";
// import {ReactSVGPanZoom} from 'react-svg-pan-zoom';
import * as globals from "./globals";
import graphUtil from "../util/graphUtil";

import Axes from "./graphAxes";
import Comments from "./graphComments";
import Participants from "./graphParticipants";
import Hulls from "./hull";
import BarChartsForGroupVotes from "./barChartsForGroupVotes";
import ExploreTid from "./exploreTid";
import TidCarousel from "./tidCarousel";
import Vote from "./voteView";

let ptptoiScaleFactor = 0.5;

class Graph extends React.Component {

  constructor(props) {
    super(props);
    this.hullElems = [];
    this.Viewer = null;
    this.state = {
      selectedComment: null,
    };
  }

  componentWillMount() {
    document.getElementById("helpTextGroups").style.display = "none";
    document.getElementById("visualization_div").style.display = "none";
    document.getElementById("carouselPane").style.display = "none";
    document.getElementsByClassName("groupSelectionView")[0].style.display = "none";
  }

  handleCommentHover(selectedComment) {
    return () => {
      document.getElementById("readReactView").style.display = "none";
      this.setState({selectedComment});
    }
  }

  handleCommentClick(selectedComment) {
    return () => {
      document.getElementById("readReactView").style.display = "none";
      this.setState({selectedComment});
    }
  }

  handleReturnToVoteClicked() {
    document.getElementById("readReactView").style.display = "block";
    this.setState({selectedComment: null})
  }

  getHullElems(gid) {
    return (elem) => {
      if (elem !== null) {
        this.hullElems[gid] = elem;
      }
    }
  }

  render() {

    if (!this.props.math) {
      return null;
    }

    let tidsToShowSet = _.keyBy(this.props.tidsToShow);

    let {
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCornerAssignments,
    } = graphUtil(this.props.comments, this.props.math, this.props.badTids);

    let should_only_show_voted_on_comments = false;

    commentsPoints = commentsPoints.filter((c) => {
      return !should_only_show_voted_on_comments || !_.isUndefined(tidsToShowSet[c.tid]);
    });
    let tidCarouselComments = this.props.comments.filter((c) => {
      return !should_only_show_voted_on_comments || !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let heading = (
 Opinion Graph

        This graph shows all people and all comments.

        Comments, identified by their number, are positioned more closely to comments that were voted on similarly (blue, in the correlation matrix above). Comments are positioned further away from comments that tended to be voted on differently (red, in the correlation matrix above).

People are positioned closer to the comments on which they agreed, and further from the comments on which they disagreed. Groups of participants that tended to vote similarly across many comments (elaborated in the previous section) are identified by their similar color.

);

    return (

        {this.props.renderHeading ? heading : ""}
        {
          this.state.selectedComment ?
          <ExploreTid
            handleReturnToVoteClicked={this.handleReturnToVoteClicked.bind(this)}
            selectedComment={this.state.selectedComment}
            votesByMe={this.props.votesByMe}
            onVoteClicked={this.props.onVoteClicked}
            comments={this.props.comment}/> :
          <Vote
            />
        }
        <TidCarousel
          commentsToShow={tidCarouselComments}
          handleCommentClick={this.handleCommentClick.bind(this)}
          />
        <svg width="100%" height={globals.side}>

          {/* Comment https://bl.ocks.org/mbostock/7555321 */}
          <g transform={`translate(${globals.side / 2}, ${15})`}>
            <text
              style={{
                fontFamily: "Georgia",
                fontSize: 14,
                fontStyle: "italic"
              }}
              textAnchor="middle">

            </text>
          </g>
          <Axes xCenter={xCenter} yCenter={yCenter} report={this.props.report}/>
          <Hulls
            getHullElems={this.getHullElems.bind(this)}
            hulls={hulls} />
          <Participants points={baseClustersScaled} ptptois={this.props.ptptois} ptptoiScaleFactor={ptptoiScaleFactor}/>
          <Comments
            commentsPoints={commentsPoints}
            selectedComment={this.state.selectedComment}
            handleCommentHover={this.handleCommentHover.bind(this)}
            points={commentsPoints}
            repfulAgreeTidsByGroup={this.props.repfulAgreeTidsByGroup}
            repfulDisageeTidsByGroup={this.props.repfulDisageeTidsByGroup}
            xx={xx}
            yy={yy}
            xCenter={xCenter}
            yCenter={yCenter}
            xScaleup={commentScaleupFactorX}
            yScaleup={commentScaleupFactorY}
            formatTid={this.props.formatTid}/>
          <BarChartsForGroupVotes
            hullElems={this.hullElems}
            selectedComment={this.state.selectedComment}
            allComments={this.props.comments}
            groups={window.preload.firstMath["group-votes"]}
            groupCornerAssignments={groupCornerAssignments}
            />
        </svg>

    );
  }
}

export default Graph;

          // <defs>
          //   <marker
          //     className={'helpArrow'}
          //     id={'ArrowTip'}
          //     viewBox={'0 0 14 14'}
          //     refX={'1'
          //     refY={'5'}
          //     markerWidth={'5'}
          //     markerHeight={'5'}
          //     orient={'auto'}>
          //     // "<path d='M 0 0 L 10 5 L 0 10 z' />
          //     <circle cx = {'6'} cy = {'6'} r = {'5'} />
          //   </marker>
          //   <clipPath id={"clipCircleVis2"}>
          //     <circle r={ptptOiRadius * ptptoiScaleFactor} cx={0} cy={0}/>
          //   </clipPath>
          //   <filter id={'colorMeMatrix'}>
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'0.33 0.33 0.33 0 0
          //       0.33 0.33 0.33 0 0
          //       0.33 0.33 0.33 0 0
          //       0 0 0 1 0'} />
          //   </filter>

          //   <filter id={'colorMeMatrixRed'}
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'1.00 0.60 0.60 0 0.3
          //         0.10 0.20 0.10 0 0
          //         0.10 0.10 0.20 0 0
          //         0 0 0 1 0'} />
          //   </filter>

          //   <filter id={'colorMeMatrixGreen'}>
          //     <feColorMatrix
          //       in={'SourceGraphic'}
          //       type={'matrix'}
          //       values={'0.20 0.10 0.10 0 0
          //         0.60 1.00 0.60 0 0.3
          //         0.10 0.10 0.40 0 0
          //         0 0 0 1 0'} />
          //   </filter>
          // </defs>

// {/* this.props.math["group-clusters"].map((cluster, i) => {
//   return (<text x={300} y={300}> Renzi Supporters </text>)
// }) : null */}

// componentDidMount() {
//   this.Viewer.fitToViewer();
// }
//

//   <button onClick={event => this.Viewer.zoomOnViewerCenter(1.1)}>Zoom in</button>
//   <button onClick={event => this.Viewer.fitSelection(40, 40, 200, 200)}>Zoom area</button>
//   <button onClick={event => this.Viewer.fitToViewer()}>Fit</button>
//

// <ReactSVGPanZoom
//   style={{outline: "1px solid black", fill: "white"}}
//   width={500} height={500} ref={Viewer => this.Viewer = Viewer}
//   onClick={event => console.log('click', event.x, event.y, event.originalEvent)}
//   onMouseMove={event => console.log('move', event.x, event.y)} >
//
// </ReactSVGPanZoom>
<|endoftext|>


<commit_before>window.quest = {};

quest.user = function() {
	var name;
	var score;
	var settings = {};

	return {
		setName : function(str) {
			name = str;
			return this;
		},

		getInfo : function() {
			return {
				this.name : name,
				this.score : score
			}
		}
	}
}()

quest.start = function() {

	//will have to use prompt method for now until console fully becomes UI
	var user = quest.user;
	var name = prompt("Please enter your name:");

	// default name
	if(name === "" || name === null) {
		name =  "The-one-who-shall-not-be-named";
	}

	user.setName(name);

	console.log("Hello " + user.getName());

	// user settings pseudocode
	function settings = {

		// difficulty

		// topic
	}
	settings();

	// start adventure
	quest.adventure();
}

window.onload = quest.start;
<commit_msg>Update start.js<commit_after>
window.quest = {};

quest.user = function() {
	var name;
	var score;

	return {
		setName : function(str) {
			name = str;
			return this;
		},

		getInfo : function() {
			return {
				this.name : name,
				this.score : score,
			}
		}
	}
}()

quest.start = function() {

	//will have to use prompt method for now until console fully becomes UI
	var user = quest.user;
	var name = prompt("Please enter your name:");

	// default name
	if(name === "" || name === null) {
		name =  "The-one-who-shall-not-be-named";
	}

	user.setName(name);

	console.log("Hello " + user.getName());

	// user settings pseudocode
	var settings = function() {

		// difficulty

		// topic

		// return object containing all settings
		return {};
	}
	settings();

	// start adventure with given settings
	quest.adventure(settings);
}

window.onload = quest.start;
<|endoftext|>


<commit_before>

// sweep(0) => 0
// sweep(1) => 1
// swepp(2) => 0
var sweep = function(t) {
  return Math.sin( // soften toothsaw
    Math.min(1, Math.max(-1, // flatten edges of toothsaw
      Math.asin(Math.sin(π*(t-0.5)))*0.7 // toothsaw
    ))
    *π/2
  )
  *0.5+0.5; // keep values between 0 and 1
};

var create_clock = function(duration) {
  var base;
  var paused;
  var waiting = {};

  var getT = function(now) {
    if (base === undefined) {
      return 0;
    }

    if (paused !== undefined) {
      return paused - base;
    }

    return (now - base);
  };

  var getVal = function(now) {
    if (base === undefined) {
      return 0;
    }

    return sweep(getT(now) / 1000 / duration);
  };

  var get = function() {
    if (base === undefined) {
      return 0;
    }

    var now = +new Date;
    var val = getVal(now);

    if (paused === undefined) {
      var k;
      for (k in waiting) {
        if (waiting.hasOwnProperty(k)) {
          if (waiting[k].check(val)) {
            waiting[k].callback();
            delete waiting[k];
          }
        }
      }
    }

    return val;
  };

  var start = function() {
    base = +new Date;
  };

  var pause = function() {
    if (base === undefined) {
      return;
    }

    paused = +new Date;
  };

  var pauseAt = function(val) {
    waitTill('pause', val, pause);
    if (base === undefined) {
      return;
    }
  };

  var resume = function() {
    if (base === undefined) {
      base = +new Date;
      return;
    } else {
      if (paused !== undefined) {
        var now = +new Date;
        base = base + (now - paused) // progress the base by the pause time

        paused = undefined;
      }
    }
  };

  var waitTill = function(key, val, callback) {
    var now = +new Date;
    var cur_val = getVal(now);

    if (val > cur_val) {
      waiting[key] = {
        check: function(v) {
          return (v >= val);
        },
        callback: callback
      };
    } else {
      waiting[key] = {
        check: function(v) {
          return (v <= val);
        },
        callback: callback
      };
    }
  };

  return {
    get: get,
    start: start,
    pause: pause,
    resume: resume,
    pauseAt: pauseAt,
    waitTill, waitTill
  };
};

var steps = [].concat(
  [
    { key: 'cover' },
    { key: 'intro-title' }
  ],

  (function() {
    var intro_example_go = {
      attach: function(step) {
        step.addClass('intro-example-go');
      },
      detachPrev: function(step) {
        step.removeClass('intro-example-go');
      }
    };

    var result = [];
    for (var i = 1; i <= 7; i++) {
      result.push({ key: 'intro-' + i});
      result.push(jQuery.extend({ key: 'intro-' + i}, intro_example_go));
    }

    return result;
  })(),

  (function() {
    var mathbox;

    var clock = create_clock(3);

    var c = [[0, 0], [0.25, 0.1], [0.25, 1], [1,1]];

    var decasteljau = function(i, j, t0) {
      if (j == 0) {
        return c[i];
      }

      var a = decasteljau(i, j-1, t0);
      var b = decasteljau(i+1, j-1, t0);

      var u0 = 1.0 - t0;
      return [
        a[0] * u0 + b[0] * t0,
        a[1] * u0 + b[1] * t0
      ];
    };

    var setupBox = function(step) {
      if (mathbox === undefined) {
        var element = $('.bezier', step).get(0);
        mathbox = mathBox(element, {}).start();

        mathbox.world().tRenderer().setClearColorHex(demo_colors.black, 0);
        mathbox
        // Cartesian viewport
        .viewport({
          type: 'cartesian',
          range: [[0, 1], [0, 1]],
          scale: [1, 1],
        })

        // Grid
        .grid({
          axis: [0, 1],
          color: demo_colors.dark_gray,
          lineWidth: 1,
        });

        setupElements();
      }
    };

    var setupElements = function() {
      // main curve
      mathbox.bezier({
        id: 'bezier-curve',
        domain: [0, 0],
        data: c,
        order: 3,
        color: demo_colors.green,
        zIndex: 1,
        opacity: 1
      });

      (function() {
        var i, j;
        var colors = ['yellow', 'blue', 'red', 'green'];

        for (j = 0; j < 4; j++) {
          for (i = 0; i < (4 - j); i++) {
            (function(i, j) {
              mathbox.curve({
                id: 'bezier-point-' + j + '-' + i,
                n: 1,
                opacity: 0,
                domain: [0, 1],
                expression: function (x) {
                  return decasteljau(i, j, clock.get());
                },
                points: true,
                line: false,
                color: demo_colors[colors[j]],
                pointSize: j > 0 ? 15 : 20,
                zIndex: j > 0 ? (2*j) : 10,
              });

              if (i < (3 - j)) {
                mathbox.bezier({
                  id: 'bezier-polygon-' + j + '-' + i,
                  n: 64,
                  domain: [0, 1],
                  expression: function (ii) {
                    return decasteljau(i + ii, j, clock.get());
                  },
                  order: 1,
                  color: demo_colors[colors[j]],
                  opacity: 0,
                  zIndex: 1 + (2 * j),
                });
              }
            })(i, j);
          }
        }
      })();

      mathbox.bezier({
        id: 'bezier-curve-dynamic',
        domain: [0, 1],
        expression: function(i) {
          return decasteljau(0, i, clock.get());
        },
        order: 3,
        color: demo_colors.green,
        zIndex: 1,
        opacity: 0,
      });
    };

    return [
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-curve', { domain: [0, 1] }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-curve', { domain: [0, 0] }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-point-0-0', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-1', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-2', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-3', { opacity: 1 }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-point-0-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-1', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-2', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-3', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-curve', { domain: [1, 1] }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-curve', { domain: [0, 1] }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-polygon-0-0', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-1', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-2', { opacity: 1 }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-0-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-1', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-2', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.set('#bezier-point-1-0', { opacity: 1 });
          mathbox.set('#bezier-point-1-1', { opacity: 1 });
          mathbox.set('#bezier-point-1-2', { opacity: 1 });
          clock.resume();
        },
        detachPrev: function(step) {
          clock.waitTill('point-1', 0, function() {
            mathbox.set('#bezier-point-1-0', { opacity: 0 });
            mathbox.set('#bezier-point-1-1', { opacity: 0 });
            mathbox.set('#bezier-point-1-2', { opacity: 0 });
            clock.pause();
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('polygon-1', 0.5, function() {
            mathbox.animate('#bezier-polygon-1-0', { opacity: 1 }, { duration: 500 });
            mathbox.animate('#bezier-polygon-1-1', { opacity: 1 }, { duration: 500 });
          });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-1-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-1-1', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('points-2', 0, function() {
            mathbox.set('#bezier-point-2-0', { opacity: 1 });
            mathbox.set('#bezier-point-2-1', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('point-2', 0, function() {
            mathbox.set('#bezier-point-2-0', { opacity: 0 });
            mathbox.set('#bezier-point-2-1', { opacity: 0 });
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('polygon-2', 0.5, function() {
            mathbox.animate('#bezier-polygon-2-0', { opacity: 1 }, { duration: 500 });
          });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-2-0', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('points-3', 0, function() {
            mathbox.set('#bezier-point-3-0', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('points-3', 0, function() {
            mathbox.set('#bezier-point-3-0', { opacity: 0 });
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.resume();
          clock.waitTill('curve-dynamic', 0, function() {
            mathbox.set('#bezier-curve-dynamic', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('curve-dynamic', 0, function() {
            mathbox.set('#bezier-curve-dynamic', { opacity: 0 });
          });
        },
        detachNext: function(step) {
          clock.pause();
        }},
      // { key: 'bezier-1',
      //   attach: function(step) {
      //     setupBox(step);
      //     clock.pauseAt(0.65);
      //   },
      //   detachPrev: function(step) {
      //     clock.resume();
      //   }},
    ];
  })(),
  [
    { key: 'decasteljau' },
    { key: 'decasteljau-numbers' }
  ]
);
<commit_msg>Hide stats for mathbox<commit_after>

// sweep(0) => 0
// sweep(1) => 1
// swepp(2) => 0
var sweep = function(t) {
  return Math.sin( // soften toothsaw
    Math.min(1, Math.max(-1, // flatten edges of toothsaw
      Math.asin(Math.sin(π*(t-0.5)))*0.7 // toothsaw
    ))
    *π/2
  )
  *0.5+0.5; // keep values between 0 and 1
};

var create_clock = function(duration) {
  var base;
  var paused;
  var waiting = {};

  var getT = function(now) {
    if (base === undefined) {
      return 0;
    }

    if (paused !== undefined) {
      return paused - base;
    }

    return (now - base);
  };

  var getVal = function(now) {
    if (base === undefined) {
      return 0;
    }

    return sweep(getT(now) / 1000 / duration);
  };

  var get = function() {
    if (base === undefined) {
      return 0;
    }

    var now = +new Date;
    var val = getVal(now);

    if (paused === undefined) {
      var k;
      for (k in waiting) {
        if (waiting.hasOwnProperty(k)) {
          if (waiting[k].check(val)) {
            waiting[k].callback();
            delete waiting[k];
          }
        }
      }
    }

    return val;
  };

  var start = function() {
    base = +new Date;
  };

  var pause = function() {
    if (base === undefined) {
      return;
    }

    paused = +new Date;
  };

  var pauseAt = function(val) {
    waitTill('pause', val, pause);
    if (base === undefined) {
      return;
    }
  };

  var resume = function() {
    if (base === undefined) {
      base = +new Date;
      return;
    } else {
      if (paused !== undefined) {
        var now = +new Date;
        base = base + (now - paused) // progress the base by the pause time

        paused = undefined;
      }
    }
  };

  var waitTill = function(key, val, callback) {
    var now = +new Date;
    var cur_val = getVal(now);

    if (val > cur_val) {
      waiting[key] = {
        check: function(v) {
          return (v >= val);
        },
        callback: callback
      };
    } else {
      waiting[key] = {
        check: function(v) {
          return (v <= val);
        },
        callback: callback
      };
    }
  };

  return {
    get: get,
    start: start,
    pause: pause,
    resume: resume,
    pauseAt: pauseAt,
    waitTill, waitTill
  };
};

var steps = [].concat(
  [
    { key: 'cover' },
    { key: 'intro-title' }
  ],

  (function() {
    var intro_example_go = {
      attach: function(step) {
        step.addClass('intro-example-go');
      },
      detachPrev: function(step) {
        step.removeClass('intro-example-go');
      }
    };

    var result = [];
    for (var i = 1; i <= 7; i++) {
      result.push({ key: 'intro-' + i});
      result.push(jQuery.extend({ key: 'intro-' + i}, intro_example_go));
    }

    return result;
  })(),

  (function() {
    var mathbox;

    var clock = create_clock(3);

    var c = [[0, 0], [0.25, 0.1], [0.25, 1], [1,1]];

    var decasteljau = function(i, j, t0) {
      if (j == 0) {
        return c[i];
      }

      var a = decasteljau(i, j-1, t0);
      var b = decasteljau(i+1, j-1, t0);

      var u0 = 1.0 - t0;
      return [
        a[0] * u0 + b[0] * t0,
        a[1] * u0 + b[1] * t0
      ];
    };

    var setupBox = function(step) {
      if (mathbox === undefined) {
        var element = $('.bezier', step).get(0);
        mathbox = mathBox(element, {
          stats: false,
        }).start();

        mathbox.world().tRenderer().setClearColorHex(demo_colors.black, 0);
        mathbox
        // Cartesian viewport
        .viewport({
          type: 'cartesian',
          range: [[0, 1], [0, 1]],
          scale: [1, 1],
        })

        // Grid
        .grid({
          axis: [0, 1],
          color: demo_colors.dark_gray,
          lineWidth: 1,
        });

        setupElements();
      }
    };

    var setupElements = function() {
      // main curve
      mathbox.bezier({
        id: 'bezier-curve',
        domain: [0, 0],
        data: c,
        order: 3,
        color: demo_colors.green,
        zIndex: 1,
        opacity: 1
      });

      (function() {
        var i, j;
        var colors = ['yellow', 'blue', 'red', 'green'];

        for (j = 0; j < 4; j++) {
          for (i = 0; i < (4 - j); i++) {
            (function(i, j) {
              mathbox.curve({
                id: 'bezier-point-' + j + '-' + i,
                n: 1,
                opacity: 0,
                domain: [0, 1],
                expression: function (x) {
                  return decasteljau(i, j, clock.get());
                },
                points: true,
                line: false,
                color: demo_colors[colors[j]],
                pointSize: j > 0 ? 15 : 20,
                zIndex: j > 0 ? (2*j) : 10,
              });

              if (i < (3 - j)) {
                mathbox.bezier({
                  id: 'bezier-polygon-' + j + '-' + i,
                  n: 64,
                  domain: [0, 1],
                  expression: function (ii) {
                    return decasteljau(i + ii, j, clock.get());
                  },
                  order: 1,
                  color: demo_colors[colors[j]],
                  opacity: 0,
                  zIndex: 1 + (2 * j),
                });
              }
            })(i, j);
          }
        }
      })();

      mathbox.bezier({
        id: 'bezier-curve-dynamic',
        domain: [0, 1],
        expression: function(i) {
          return decasteljau(0, i, clock.get());
        },
        order: 3,
        color: demo_colors.green,
        zIndex: 1,
        opacity: 0,
      });
    };

    return [
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-curve', { domain: [0, 1] }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-curve', { domain: [0, 0] }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-point-0-0', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-1', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-2', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-3', { opacity: 1 }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-point-0-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-1', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-2', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-point-0-3', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-curve', { domain: [1, 1] }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-curve', { domain: [0, 1] }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.animate('#bezier-polygon-0-0', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-1', { opacity: 1 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-2', { opacity: 1 }, { duration: 500 });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-0-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-1', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-0-2', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          mathbox.set('#bezier-point-1-0', { opacity: 1 });
          mathbox.set('#bezier-point-1-1', { opacity: 1 });
          mathbox.set('#bezier-point-1-2', { opacity: 1 });
          clock.resume();
        },
        detachPrev: function(step) {
          clock.waitTill('point-1', 0, function() {
            mathbox.set('#bezier-point-1-0', { opacity: 0 });
            mathbox.set('#bezier-point-1-1', { opacity: 0 });
            mathbox.set('#bezier-point-1-2', { opacity: 0 });
            clock.pause();
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('polygon-1', 0.5, function() {
            mathbox.animate('#bezier-polygon-1-0', { opacity: 1 }, { duration: 500 });
            mathbox.animate('#bezier-polygon-1-1', { opacity: 1 }, { duration: 500 });
          });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-1-0', { opacity: 0 }, { duration: 500 });
          mathbox.animate('#bezier-polygon-1-1', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('points-2', 0, function() {
            mathbox.set('#bezier-point-2-0', { opacity: 1 });
            mathbox.set('#bezier-point-2-1', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('point-2', 0, function() {
            mathbox.set('#bezier-point-2-0', { opacity: 0 });
            mathbox.set('#bezier-point-2-1', { opacity: 0 });
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('polygon-2', 0.5, function() {
            mathbox.animate('#bezier-polygon-2-0', { opacity: 1 }, { duration: 500 });
          });
        },
        detachPrev: function(step) {
          mathbox.animate('#bezier-polygon-2-0', { opacity: 0 }, { duration: 500 });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.waitTill('points-3', 0, function() {
            mathbox.set('#bezier-point-3-0', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('points-3', 0, function() {
            mathbox.set('#bezier-point-3-0', { opacity: 0 });
          });
        }},
      { key: 'bezier-1',
        attach: function(step) {
          setupBox(step);
          clock.resume();
          clock.waitTill('curve-dynamic', 0, function() {
            mathbox.set('#bezier-curve-dynamic', { opacity: 1 });
          });
        },
        detachPrev: function(step) {
          clock.waitTill('curve-dynamic', 0, function() {
            mathbox.set('#bezier-curve-dynamic', { opacity: 0 });
          });
        },
        detachNext: function(step) {
          clock.pause();
        }},
      // { key: 'bezier-1',
      //   attach: function(step) {
      //     setupBox(step);
      //     clock.pauseAt(0.65);
      //   },
      //   detachPrev: function(step) {
      //     clock.resume();
      //   }},
    ];
  })(),
  [
    { key: 'decasteljau' },
    { key: 'decasteljau-numbers' }
  ]
);
<|endoftext|>


<commit_before>import { createStore } from 'redux';
import reducer from './reducers';

const store = createStore(reducer);

export default store;
<commit_msg>working redux devtools<commit_after>import { createStore, compose } from 'redux';
import reducer from './reducers';

const store = createStore(reducer, compose(typeof window ==='object' && typeof window.devToolsExtension !=='undefined' ? window.devToolsExtension() : f => f));

export default store;
<|endoftext|>


<commit_before>var audioCtx = new AudioContext();
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.start();

function trigger() {
  console.log("trigger");
  gainNode.gain.setValueAtTime(0.5, audioCtx.currentTime);
  gainNode.gain.setTargetAtTime(0.0, audioCtx.currentTime + 0.01, 0.5);
}

var mute = document.querySelector('.mute');
mute.ontouchstart = trigger;
mute.onclick= trigger;

/*
var initialFreq = 800;
var initialVol = 0.1;
var dotTime = 200
oscillator.type = 'sine';
oscillator.frequency.value = initialFreq; // value in hertz
oscillator.start();

gainNode.gain.value = initialVol;

var morseStatut = morseEmmit(dotTime);

function morseEmmit(dotTime){
  if ( morseStatut != null )
  {
    gainNode.connect(audioCtx.destination);
    window.setTimeout("gainNode.disconnect(audioCtx.destination)", 1200);
  }
  else
  {
    window.setTimeout("morseEmmit(dotTime);",100);
  }
}

function computeVariable(morseStatut) {
  // arithmetic operations that use myVar [2]
}

// mute button
var mute = document.querySelector('.mute');
mute.onclick = function() {
  morseEmmit(300);
};
*/
<commit_msg>Clean synth code, add more oscillator properties<commit_after>var audioCtx = new AudioContext();
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
var initialFreq = 800;
var initialVol = 0.1;
var dotTime = 200
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
gainNode.gain.value = initialVol;
oscillator.connect(gainNode);
oscillator.type = 'sine';
oscillator.frequency.value = initialFreq; // value in hertz

gainNode.connect(audioCtx.destination);
oscillator.start();

function trigger() {
  gainNode.gain.setValueAtTime(0.8, audioCtx.currentTime);
  gainNode.gain.setTargetAtTime(0.0, audioCtx.currentTime + 0.0, 0.1);
}

var mute = document.querySelector('.mute');
mute.ontouchstart = trigger;
mute.onclick= trigger;

<|endoftext|>


<commit_before>/*
 Backporting "visuallyselected" for Firefox 31-40

 See also:
   http://www.hackermusings.com/2015/06/electrolysis-a-tale-of-tab-switching-and-themes/

 Usage:
   Components.utils.import(".../path/to/visuallyselectedTabs.jsm");
   visuallyselectedTabs(gBrowser);

 license: The MIT License, Copyright (c) 2015 YUKI "Piro" Hiroshi
 original:
   http://github.com/piroor/fxaddonlib-visuallyselected-tabs
*/

var EXPORTED_SYMBOLS = ['visuallyselectedTabs'];

Components.utils.import('resource://gre/modules/Services.jsm');

function setVisuallySelected(aNode, aSelected) {
  if (!aNode || typeof aNode.setAttribute != 'function')
    return;

  if (aSelected)
    aNode.setAttribute('visuallyselected', true);
  else
    aNode.removeAttribute('visuallyselected');

  Array.forEach(aNode.childNodes, function(aChild) {
    setVisuallySelected(aChild, aSelected);
  });

  var anonymousChildren = aNode.ownerDocument.getAnonymousNodes(aNode);
  if (anonymousChildren && anonymousChildren.length > 0)
    Array.forEach(anonymousChildren, function(aAnonymousChild) {
      setVisuallySelected(aAnonymousChild, aSelected);
    });
}

function visuallyselectedTabs(aTabBrowser) {
  if (!aTabBrowser ||
      aTabBrowser.localName != 'tabbrowser' ||
      aTabBrowser.__visuallyselectedTabsInstalled ||
      Services.vc.compare(Services.appinfo.platformVersion, '41.0a1') >= 0)
    return;

  aTabBrowser.__visuallyselectedTabsInstalled = true;

  var document = aTabBrowser.ownerDocument;

  function onTabSelect(aEvent) {
    var prevTab = aEvent.detail && aEvent.detail.previousTab;
    if (prevTab)
      setVisuallySelected(prevTab, false);

    setVisuallySelected(aEvent.originalTarget, true);
  }

  var tabsContainer = aTabBrowser.tabContainer;
  tabsContainer.addEventListener('TabSelect', onTabSelect, false);
  document.addEventListener('unload', function onUnload(aEvent) {
    document.removeEventListener('unload', onUnload, false);
    tabsContainer.removeEventListener('TabSelect', onTabSelect, false);
  }, false);
}
<commit_msg>Set visuallyselected attribute for the initially selected tab<commit_after>/*
 Backporting "visuallyselected" for Firefox 31-40

 See also:
   http://www.hackermusings.com/2015/06/electrolysis-a-tale-of-tab-switching-and-themes/

 Usage:
   Components.utils.import(".../path/to/visuallyselectedTabs.jsm");
   visuallyselectedTabs(gBrowser);

 license: The MIT License, Copyright (c) 2015 YUKI "Piro" Hiroshi
 original:
   http://github.com/piroor/fxaddonlib-visuallyselected-tabs
*/

var EXPORTED_SYMBOLS = ['visuallyselectedTabs'];

Components.utils.import('resource://gre/modules/Services.jsm');

function setVisuallySelected(aNode, aSelected) {
  if (!aNode || typeof aNode.setAttribute != 'function')
    return;

  if (aSelected)
    aNode.setAttribute('visuallyselected', true);
  else
    aNode.removeAttribute('visuallyselected');

  Array.forEach(aNode.childNodes, function(aChild) {
    setVisuallySelected(aChild, aSelected);
  });

  var anonymousChildren = aNode.ownerDocument.getAnonymousNodes(aNode);
  if (anonymousChildren && anonymousChildren.length > 0)
    Array.forEach(anonymousChildren, function(aAnonymousChild) {
      setVisuallySelected(aAnonymousChild, aSelected);
    });
}

function visuallyselectedTabs(aTabBrowser) {
  if (!aTabBrowser ||
      aTabBrowser.localName != 'tabbrowser' ||
      aTabBrowser.__visuallyselectedTabsInstalled ||
      Services.vc.compare(Services.appinfo.platformVersion, '41.0a1') >= 0)
    return;

  aTabBrowser.__visuallyselectedTabsInstalled = true;

  var document = aTabBrowser.ownerDocument;

  function onTabSelect(aEvent) {
    var prevTab = aEvent.detail && aEvent.detail.previousTab;
    if (prevTab)
      setVisuallySelected(prevTab, false);

    setVisuallySelected(aEvent.originalTarget, true);
  }

  var tabsContainer = aTabBrowser.tabContainer;
  tabsContainer.addEventListener('TabSelect', onTabSelect, false);
  setVisuallySelected(aTabBrowser.selectedTab, true);
  document.addEventListener('unload', function onUnload(aEvent) {
    document.removeEventListener('unload', onUnload, false);
    tabsContainer.removeEventListener('TabSelect', onTabSelect, false);
  }, false);
}
<|endoftext|>


<commit_before>var table = (function(fps, billiard, undefined){
	var table = new billiard.Table({ width: 320, height: 240 });
	table.addBall({ x: 0, y: 1, vx: 3, vy: 2, r: 10 });
	return table;
})(fps, billiard);
<commit_msg>allow for a variable number of balls<commit_after>var table = (function(fps, billiard, undefined){
	function range(l, h) {
		var result = [];
		while (h > l) { result[--h] = h; }
		return result;
	}

	var options = { width: 320, height: 240, collisions: false };
	var table = new billiard.Table(options);

	(range(0, 1)).forEach(function(_, index){
		var x = Math.floor(2 * options.width * (Math.random() - 1/2));
		var y = Math.floor(2 * options.height * (Math.random() - 1/2));
		var vx = Math.floor(10 * (Math.random() - 1/2));
		var vy = Math.floor(6 * (Math.random() - 1/2));
		table.addBall({ x: x, y: y, vx: vx, vy: vy, r: 10 });
	});
	return table;
})(fps, billiard);
<|endoftext|>


<commit_before>function appendToWidget(a, b, c, d) {
    a = document.querySelector(a);
    b = document.createElement(b);
    b.innerHTML = d;
    b.className += c;
    a.appendChild(b)
}
function getJSON(a, b) {
    var c = new XMLHttpRequest;
    c.open("GET", a, !0);
    c.onload = function() {
        if (200 === c.status) {
            var a = JSON.parse(c.responseText);
            b(a)
        }
    };
    c.send()
}
function ready(a) {
    "loading" != document.readyState ? a() : document.addEventListener("DOMContentLoaded", a)
}
function start() {
    appendToWidget("body", "style", "", "@import url(https://fonts.googleapis.com/css?family=Noto+Sans:400,700);.gh-widget-link,.gh-widget-link:hover{text-decoration:none}.gh-widget-container{display:flex;flex-direction:row;flex-wrap:no-wrap;align-items:center;justify-content:center;color:#333;font-family:'Noto Sans',sans-serif}.gh-widget-personal-details .bio{color:#222222l;} .gh-widget-stats .count{color:#4078C0}.github-widget{border:1px solid #DDD;max-width:350px}.gh-widget-item{flex:1;text-align:center;padding:10px}.gh-widget-repositories .language{text-align:left}.gh-widget-repositories .language div,.gh-widget-repositories .stars div{padding:5px 0}.gh-widget-photo{flex:2}.gh-widget-photo img{border-radius:100%;max-width:80px}.gh-widget-personal-details{flex:6}.gh-widget-personal-details .full-name{font-size:1.5em;line-height:1.5em}.gh-widget-personal-details .location{font-size:.8em}.gh-widget-stats .count{font-size:1.2em;font-weight:700}.gh-widget-repositories .names{flex:2;text-align:left}.gh-widget-repositories .names div{padding:5px 0;text-overflow:ellipsis}.gh-widget-follow{flex:2}.gh-widget-active-time{flex:4;font-size:.8em}.gh-widget-heading{font-weight:400;color:#666}.gh-widget-hr{border:1px solid #DDD}.gh-widget-link{color:#4078C0}.gh-widget-follow button{width:100%;height:2em;border:none;background:#ddd} img{ vertical-align:middle;} .github-box-title{position:relative;border-bottom:1px solid #DDD;border-radius:3px 3px 0 0;background:#FCFCFC;background:-moz-linear-gradient(#FCFCFC,#EBEBEB);background:-webkit-linear-gradient(#FCFCFC,#EBEBEB);}");
    for (var a = document.querySelectorAll(".github-widget"), b = 0; b < a.length; b++) {
        var c = a[b];
        c.setAttribute("id", "widget" + b);
        appendToWidget("#widget" + b, "div", "", '

Popular Repositories

');
        c = c.dataset.username;
        fetchRepos(c, "#widget" + b);
        fetchUserDetails(c, "#widget" + b)
    }
}
ready(start);
function fetchRepos(a, b) {
	getJSON("https://api.github.com/users/JustWayward/repos",
    function(a) {
        updateRepoDetails(topRepos(a), b);
    })

    getJSON("https://api.github.com/users/" + a + "/repos",
    function(a) {
        updateRepoDetails(topRepos(a), b);
        updateLastPush(lastPushedDay(a), b)
    })
}
function fetchUserDetails(a, b) {
    getJSON("https://api.github.com/users/" + a,
    function(a) {
        updateUserDetails(a, b)
    })
}
function updateLastPush(a, b) {
    appendToWidget(b + " .gh-widget-active-time", "span", "", "Last active: " + (a ? a + " day(s) ago": "Today"))
}
function lastPushedDay(a) {
    for (var b = new Date,
    c, d = 9999999999999,
    e = 0; e < a.length; e++) {
        var f = new Date(a[e].pushed_at);
        b - f < d && (c = f, d = b - f)
    }
    return Math.floor((b - c) / 864E5)
}
function updateUserDetails(a, b) {
    appendToWidget(b + " .gh-widget-personal-details", "div", "full-name", ''+a.name+'');
    a.bio && appendToWidget(b + " .gh-widget-personal-details", "div", "bio", a.bio);
    a.location && appendToWidget(b + " .gh-widget-personal-details", "div", "location", ''+a.location);
	a.email && appendToWidget(b + " .gh-widget-personal-details", "div", "email", ''+a.email);
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.followers + '

Followers
');
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.following + '

Following
');
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.public_repos + '

Repositories
');
    appendToWidget(b + " .gh-widget-photo", "span", "", '');
    appendToWidget(b + " .gh-widget-follow", "button", "", 'Home')
}
function updateRepoDetails(a, b) {
    for (var c = 0; c < a.length; c++)
	    if(a[c].language)
		appendToWidget(b + " .gh-widget-repositories", "div", "gh-widget-container", '

' + a[c].name + '

' + (a[c].language ? a[c].language: "Unknown") + '

★' + a[c].stars + "

")
}
function topRepos(a) {
    a.sort(function(a, b) {
        return a.stargazers_count === b.stargazers_count ? 0 : a.stargazers_count > b.stargazers_count ? -1 : 1
    });
    a = a.slice(0, 3);
    var b = [],
    c;
    for (c in a) {
        var d = a[c];
        b.push({
            name: d.name,
            stars: d.stargazers_count,
            language: d.language,
            repoUrl: d.html_url
        })
    }
    return b
};
<commit_msg>Update test1.js<commit_after>function appendToWidget(a, b, c, d) {
    a = document.querySelector(a);
    b = document.createElement(b);
    b.innerHTML = d;
    b.className += c;
    a.appendChild(b)
}
function getJSON(a, b) {
    var c = new XMLHttpRequest;
    c.open("GET", a, !0);
    c.onload = function() {
        if (200 === c.status) {
            var a = JSON.parse(c.responseText);
            b(a)
        }
    };
    c.send()
}
function ready(a) {
    "loading" != document.readyState ? a() : document.addEventListener("DOMContentLoaded", a)
}
function start() {
    appendToWidget("body", "style", "", "@import url(https://fonts.googleapis.com/css?family=Noto+Sans:400,700);.gh-widget-link,.gh-widget-link:hover{text-decoration:none}.gh-widget-container{display:flex;flex-direction:row;flex-wrap:no-wrap;align-items:center;justify-content:center;color:#333;font-family:'Noto Sans',sans-serif}.gh-widget-personal-details .bio{color:#222222l;} .gh-widget-stats .count{color:#4078C0}.github-widget{border:1px solid #DDD;max-width:350px}.gh-widget-item{flex:1;text-align:center;padding:10px}.gh-widget-repositories .language{text-align:left}.gh-widget-repositories .language div,.gh-widget-repositories .stars div{padding:5px 0}.gh-widget-photo{flex:2}.gh-widget-photo img{border-radius:100%;max-width:50px}.gh-widget-personal-details{flex:6}.gh-widget-personal-details .full-name{font-size:1.5em;line-height:1.5em}.gh-widget-personal-details .location{font-size:.8em}.gh-widget-stats .count{font-size:1.2em;font-weight:700}.gh-widget-repositories .names{flex:2;text-align:left}.gh-widget-repositories .names div{padding:5px 0;text-overflow:ellipsis}.gh-widget-follow{flex:2}.gh-widget-active-time{flex:4;font-size:.8em}.gh-widget-heading{font-weight:400;color:#666}.gh-widget-hr{border:1px solid #DDD}.gh-widget-link{color:#4078C0}.gh-widget-follow button{width:100%;height:2em;border:none;background:#ddd} img{ vertical-align:middle;} .github-box-title{position:relative;border-bottom:1px solid #DDD;border-radius:3px 3px 0 0;background:#FCFCFC;background:-moz-linear-gradient(#FCFCFC,#EBEBEB);background:-webkit-linear-gradient(#FCFCFC,#EBEBEB);}");
    for (var a = document.querySelectorAll(".github-widget"), b = 0; b < a.length; b++) {
        var c = a[b];
        c.setAttribute("id", "widget" + b);
        appendToWidget("#widget" + b, "div", "", '

Popular Repositories

');
        c = c.dataset.username;
        fetchRepos(c, "#widget" + b);
        fetchUserDetails(c, "#widget" + b)
    }
}
ready(start);
function fetchRepos(a, b) {
	getJSON("https://api.github.com/users/JustWayward/repos",
    function(a) {
        updateRepoDetails(topRepos(a), b);
    })

    getJSON("https://api.github.com/users/" + a + "/repos",
    function(a) {
        updateRepoDetails(topRepos(a), b);
        updateLastPush(lastPushedDay(a), b)
    })
}
function fetchUserDetails(a, b) {
    getJSON("https://api.github.com/users/" + a,
    function(a) {
        updateUserDetails(a, b)
    })
}
function updateLastPush(a, b) {
    appendToWidget(b + " .gh-widget-active-time", "span", "", "Last active: " + (a ? a + " day(s) ago": "Today"))
}
function lastPushedDay(a) {
    for (var b = new Date,
    c, d = 9999999999999,
    e = 0; e < a.length; e++) {
        var f = new Date(a[e].pushed_at);
        b - f < d && (c = f, d = b - f)
    }
    return Math.floor((b - c) / 864E5)
}
function updateUserDetails(a, b) {
    appendToWidget(b + " .gh-widget-personal-details", "div", "full-name", ''+a.name+'');
    a.bio && appendToWidget(b + " .gh-widget-personal-details", "div", "bio", a.bio);
    a.location && appendToWidget(b + " .gh-widget-personal-details", "div", "location", ''+a.location);
	a.email && appendToWidget(b + " .gh-widget-personal-details", "div", "email", ''+a.email);
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.followers + '

Followers
');
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.following + '

Following
');
    appendToWidget(b + " .gh-widget-stats", "div", "gh-widget-item", '
' + a.public_repos + '

Repos
');
    appendToWidget(b + " .gh-widget-photo", "span", "", '');
    appendToWidget(b + " .gh-widget-follow", "button", "", 'Home')
}
function updateRepoDetails(a, b) {
    for (var c = 0; c < a.length; c++)
	    if(a[c].language)
		appendToWidget(b + " .gh-widget-repositories", "div", "gh-widget-container", '

' + a[c].name + '

' + (a[c].language ? a[c].language: "Unknown") + '

★' + a[c].stars + "

")
}
function topRepos(a) {
    a.sort(function(a, b) {
        return a.stargazers_count === b.stargazers_count ? 0 : a.stargazers_count > b.stargazers_count ? -1 : 1
    });
    a = a.slice(0, 3);
    var b = [],
    c;
    for (c in a) {
        var d = a[c];
        b.push({
            name: d.name,
            stars: d.stargazers_count,
            language: d.language,
            repoUrl: d.html_url
        })
    }
    return b
};
<|endoftext|>