<commit_before>import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { fadeInUpBig, zoomIn, fadeIn } from 'react-animations';
import { StyleSheet, css } from 'aphrodite';
import axios from 'axios';
import options from './Options.js';
import Mushroom from './Mushroom.js';
import key from './key.json';
import _ from 'underscore';
import NavDrawer from '../../Drawer/Drawer.js'
import 'bootstrap/dist/css/bootstrap.css';
import './mushroomStyles.css';

class Mushrooms extends Component {

  constructor(props) {
    super(props);
    this.state = {
      currentPrediction: '',
      animation: '',
    }
    this.styles = StyleSheet.create({
      zoomIn:  {
        animationName: zoomIn,
        animationDuration: '.5s'
      },
      fadeIn:  {
        animationName: fadeIn,
        animationDuration: '1s'
      },
      fadeInUpBig: {
        animationName: fadeInUpBig,
        animationDuration: '1.5s'
      },
    })
    this.description = (

          Poisonous or Edible?

          This example uses a support vector classifier trained with over 8000 items of sample data different mushrooms and creates a binary classifier (one producing a result of true or false) that can accurately determine whether a wild mushroom is edible or poisonous.  In the original dataset, the traits are represented as words, but to train the model, they had to be converted to numerical values.  Enter selections for each criterion before selecting “Get Prediction” to see if a given mushroom is poisonous or edible.

          Support Vector Classifier

          The way this classifier works has similarities to the linear regression used in the housing prices predictor, except that it has additional dimensions in the graphical representation. In addition to the x and y-axis, it has a third axis going into 3-dimensional space that represents each trait that needs to be classified (which in this case would be the different traits of mushrooms). There is a hyperplane (a plane separating one classification from the other) going through all dimensions. If the inputted data is above the hyperplane, it gets one classification and if it is below, it gets the other.

          Pros: Very accurate classifiers can be produced with this model with smaller datasets than with some other models, it is very effective for binary classification, are appropriate for use with a large number of features.

          Cons: Training is a greater than quadratic operation, so training large sets of data is not feasible.

    )
  }

  camelCase = (str) => {
    return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) {
      return index == 0 ? letter.toLowerCase() : letter.toUpperCase();
    }).replace(/\s+/g, '');
  }

  handleSelect = (name, val) => {
    console.log(val.value);
    this.setState({
      [this.camelCase(name)]: val.value,
    })
  }

  handleSubmit = () => {
    console.log(this.state)
    axios.post('https://ml-sandbox.ml/api/mushrooms', {
      data: [
        this.state.capShape,
        this.state.capSurface,
        this.state.capColor,
        this.state.bruises,
        this.state.odor,
        1,
        this.state.gillSpacing,
        this.state.gillSize,
        this.state.gillColor,
        this.state.stalkShape,
        this.state.stalkRoot,
        2,
        2,
        7,
        7,
        0,
        this.state.veilColor,
        this.state.ringNumber,
        this.state.ringType,
        this.state.sporePrintColor,
        this.state.population,
        this.state.habitat,
      ]
    }).then((results) => {
      this.setState({
        animation: this.styles.fadeIn,
      }, () => {
        results.data.prediction === 1 ? this.setState({currentPrediction: 'Poison x('}) : this.setState({currentPrediction: 'Edible :)'});
      })
    }).catch((err) => {
      this.setState({
        animation: this.styles.zoomIn,
      }, () => {
        this.setState({
          currentPrediction: 'Did you remember to select all options?'
        })
      })
    })
  }

  render () {
    return (

        <NavDrawer modelName="ml-sandbox-mushrooms" description={this.description}/>

          {
            _.map(options, (option, name) => {
              return (
                <Mushroom
                  option={option}
                  name={name}
                  key={name}
                  id={name}
                  handleSelect={this.handleSelect.bind(this)}
                />
              );
            })
          }

          <button type='button' onClick={this.handleSubmit} className='btn-outline-secondary btn mushroom-prediction-btn'>Get Prediction</button>
          <div className={`mushroom-current-prediction ${css(this.state.animation)}`}>
            {this.state.currentPrediction === '' ? '' : this.state.currentPrediction}

    )
  }
}

export default Mushrooms;

<commit_msg>added mushrooms explanation<commit_after>import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { fadeInUpBig, zoomIn, fadeIn } from 'react-animations';
import { StyleSheet, css } from 'aphrodite';
import axios from 'axios';
import options from './Options.js';
import Mushroom from './Mushroom.js';
import key from './key.json';
import _ from 'underscore';
import NavDrawer from '../../Drawer/Drawer.js'
import 'bootstrap/dist/css/bootstrap.css';
import './mushroomStyles.css';

class Mushrooms extends Component {

  constructor(props) {
    super(props);
    this.state = {
      currentPrediction: '',
      animation: '',
    }
    this.styles = StyleSheet.create({
      zoomIn:  {
        animationName: zoomIn,
        animationDuration: '.5s'
      },
      fadeIn:  {
        animationName: fadeIn,
        animationDuration: '1s'
      },
      fadeInUpBig: {
        animationName: fadeInUpBig,
        animationDuration: '1.5s'
      },
    })
    this.description = (

          Poisonous or Edible?

          This example uses a support vector classifier trained with over 8000 items of sample data different mushrooms and creates a binary classifier (one producing a result of true or false) that can accurately determine whether a wild mushroom is edible or poisonous.  In the original dataset, the traits are represented as words, but to train the model, they had to be converted to numerical values.  Enter selections for each criterion before selecting “Get Prediction” to see if a given mushroom is poisonous or edible.

          Support Vector Classifier

          The way this classifier works has similarities to the linear regression used in the housing prices predictor, except that it has additional dimensions in the graphical representation. In addition to the x and y-axis, it has a third axis going into 3-dimensional space that represents each trait that needs to be classified (which in this case would be the different traits of mushrooms). There is a hyperplane (a plane separating one classification from the other) going through all dimensions. If the inputted data is above the hyperplane, it gets one classification and if it is below, it gets the other.

          Pros: Very accurate classifiers can be produced with this model with smaller datasets than with some other models, it is very effective for binary classification, are appropriate for use with a large number of features.

          Cons: Training is a greater than quadratic operation, so training large sets of data is not feasible.

    )
  }

  camelCase = (str) => {
    return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) {
      return index == 0 ? letter.toLowerCase() : letter.toUpperCase();
    }).replace(/\s+/g, '');
  }

  handleSelect = (name, val) => {
    console.log(val.value);
    this.setState({
      [this.camelCase(name)]: val.value,
    })
  }

  handleSubmit = () => {
    console.log(this.state)
    axios.post('https://ml-sandbox.ml/api/mushrooms', {
      data: [
        this.state.capShape,
        this.state.capSurface,
        this.state.capColor,
        this.state.bruises,
        this.state.odor,
        1,
        this.state.gillSpacing,
        this.state.gillSize,
        this.state.gillColor,
        this.state.stalkShape,
        this.state.stalkRoot,
        2,
        2,
        7,
        7,
        0,
        this.state.veilColor,
        this.state.ringNumber,
        this.state.ringType,
        this.state.sporePrintColor,
        this.state.population,
        this.state.habitat,
      ]
    }).then((results) => {
      this.setState({
        animation: this.styles.fadeIn,
      }, () => {
        results.data.prediction === 1 ? this.setState({currentPrediction: 'Poison x('}) : this.setState({currentPrediction: 'Edible :)'});
      })
    }).catch((err) => {
      this.setState({
        animation: this.styles.zoomIn,
      }, () => {
        this.setState({
          currentPrediction: 'Did you remember to select all options?'
        })
      })
    })
  }

  render () {
    return (

        <NavDrawer modelName="ml-sandbox-mushrooms" description={this.description}/>

          {
            _.map(options, (option, name) => {
              return (
                <Mushroom
                  option={option}
                  name={name}
                  key={name}
                  id={name}
                  handleSelect={this.handleSelect.bind(this)}
                />
              );
            })
          }

          <button type='button' onClick={this.handleSubmit} className='btn-outline-secondary btn mushroom-prediction-btn'>Get Prediction</button>
          <div className={`mushroom-current-prediction ${css(this.state.animation)}`}>
            {this.state.currentPrediction === '' ? '' : this.state.currentPrediction}

    )
  }
}

export default Mushrooms;

<|endoftext|>


<commit_before>
'use strict'

const _ = require('lodash')
const fs = require('fs')
const config = require('../config')
const scriptures = require("../data/scriptures")

function scriptureCount(scriptures) {
	var scripture
	var count = 0

	for(scripture in scriptures) {
		count++
	}
	return count
}

function indexJSON(obj) {
	var scriptureIndex = []
	var a

	for (a in obj) {
		scriptureIndex.push(a)
	}
	return scriptureIndex
}

function getScripture(scriptures) {
	let num = Math.floor(Math.random() * scriptureCount(scriptures))
	let scriptIndex = indexJSON(scriptures)

	var scripture = scriptures[num]
	return scripture
}

const msgDefaults = {
  response_type: 'in_channel',
  username: 'Stubot',
  icon_emoji: config('ICON_EMOJI')
}

let attachments = [
  {
    title: 'Stubot will retrieve a random scriptural thought for you.',
    color: '#2FA44F',
    text: "These are the scriptures: " + getScripture(scriptures.scriptures).location,
    mrkdwn_in: ['text']
  },
]

const handler = (payload, res) => {
  let msg = _.defaults({
    channel: payload.channel_name,
    attachments: attachments
  }, msgDefaults)

  res.set('content-type', 'application/json')
  res.status(200).json(msg)
  return
}

module.exports = { pattern: /scripture/ig, handler: handler }
<commit_msg>added scripture passage and location to output.<commit_after>
'use strict'

const _ = require('lodash')
const fs = require('fs')
const config = require('../config')
const scriptures = require("../data/scriptures")

function scriptureCount(scriptures) {
	var scripture
	var count = 0

	for(scripture in scriptures) {
		count++
	}
	return count
}

function indexJSON(obj) {
	var scriptureIndex = []
	var a

	for (a in obj) {
		scriptureIndex.push(a)
	}
	return scriptureIndex
}

function getScripture(scriptures) {
	let num = Math.floor(Math.random() * scriptureCount(scriptures))
	let scriptIndex = indexJSON(scriptures)

	var scripture = scriptures[num]
	var scripturePassage;
	for( p in scripture.passage) {
		scripturePassage += p + " "
	}
	return scripturePassage + "-" + scripture.location
}

const msgDefaults = {
  response_type: 'in_channel',
  username: 'Stubot',
  icon_emoji: config('ICON_EMOJI')
}

let attachments = [
  {
    title: 'Stubot will retrieve a random scriptural thought for you.',
    color: '#2FA44F',
    text: getScripture(scriptures.scriptures),
    mrkdwn_in: ['text']
  },
]

const handler = (payload, res) => {
  let msg = _.defaults({
    channel: payload.channel_name,
    attachments: attachments
  }, msgDefaults)

  res.set('content-type', 'application/json')
  res.status(200).json(msg)
  return
}

module.exports = { pattern: /scripture/ig, handler: handler }
<|endoftext|>


<commit_before>function handleSubmit () {
  let val = document.getElementById('url').value
  if (val) {
    document.location += 'memento/*/' + val
  }
}

function shortestFirst (a, b) {
  return a.length - b.length
}

function hideURIs () {
  document.getElementById('uris').classList.add('hidden')
  document.getElementById('memCountListLink').classList.remove('activated')
  window.localStorage.setItem('showURIs', 'false')
}

function addURIListToDOM () {
  let ul = document.getElementById('uriList')
  const uriKeys = Object.keys(uris).sort(shortestFirst)

  Object.entries(uris).forEach(([urir, mementoList]) => {
    mementoList.forEach(function (memento) {
      let li = document.createElement('li')
      let a = document.createElement('a')
      a.href = 'memento/' + memento['datetime'] + '/' + urir
      a.appendChild(document.createTextNode(urir))
      dt = document.createTextNode(' (' + memento['datetime'] + ')')

      li.appendChild(a)
      li.appendChild(dt)

      li.setAttribute('data-mime', memento['mime'])
      li.setAttribute('data-status', memento['status'])

      const isHTML = memento['mime'].toLowerCase().startsWith('text/html')
      const isARedirect = memento['status'][0] === '3'
      if (isHTML && !isARedirect) {
        li.setAttribute('data-display', 'default')
      }
      ul.appendChild(li)
    })
  })
}

function showURIs () {
  if (document.getElementById('uriList').childNodes.length === 0) {
    addURIListToDOM() // Prevent multiple adds of the URI list to the DOM
  }

  document.getElementById('memCountListLink').className = ['activated']
  document.getElementById('uris').classList.remove('hidden')
  setPlurality()
  setShowAllButtonStatus()

  setUIExpandedState(uris)
  // Maintain visible state of URI display for future retrieval
  window.localStorage.setItem('showURIs', 'true')
}

function setUIExpandedState (urisObj) {
  const urisHash = calculateURIsHash(urisObj)
  setURIsHash(urisHash)
}

function calculateURIsHash (urisObj) {
  return JSON.stringify(urisObj).hashCode()
}

function getURIsHash () {
  return window.localStorage.getItem('urisHash')
}

function setURIsHash (hashIn) {
  return window.localStorage.setItem('urisHash', hashIn)
}

String.prototype.hashCode = function () {
  let hash = 0
  let i
  let chr
  if (this.length === 0) {
    return hash
  }
  for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i)
    hash = ((hash << 5) - hash) + chr
    hash |= 0 // Convert to 32bit integer
  }
  return hash
}

function toggleURIDisplay () {
  if (window.localStorage.getItem('showURIs') === 'true') {
    hideURIs()
  } else {
    showURIs()
  }
}

function addEventListeners () {
  let target = document.getElementById('memCountListLink')
  target.addEventListener('click', toggleURIDisplay, false)

  let showAllInListingButton = document.getElementById('showEmbeddedURI')
  showAllInListingButton.onclick = function showAllURIs () {
    const uriList = document.getElementById('uriList')
    if (this.innerHTML === this.dataset.defaultvalue) {
      this.innerHTML = this.dataset.activatedvalue
      uriList.classList.add('forceDisplay')
    } else {
      this.innerHTML = this.dataset.defaultvalue
      uriList.classList.remove('forceDisplay')
    }
  }

  getIPFSWebUIAddress()
  updateServiceWorkerVersionUI()

  let reinstallServiceWorkerButton = document.getElementById('reinstallServiceWorker')
  reinstallServiceWorkerButton.onclick = reinstallServiceWorker

  setShowURIsVisibility()
}

function setShowURIsVisibility () {
  const previousHash = getURIsHash() + ''
  const newHash = calculateURIsHash(uris) + ''

  if (window.localStorage.getItem('showURIs') && previousHash === newHash) {
    showURIs()
  } else {
    hideURIs()
  }
}

function setPlurality () {
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML

  if (htmlFilesPlurality === '1') {
    document.getElementById('htmlPagesPlurality').classList.add('hidden')
  }
}

function setShowAllButtonStatus () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML
  if (urimCount === htmlFilesPlurality) {
    document.getElementById('showEmbeddedURI').setAttribute('disabled', 'disabled')
  }
}

function assignStatusButtonHandlers () {
  let button = document.getElementsByTagName('button')[0]
  if (button.innerHTML === 'Start') {
    button.addEventListener('click', startIPFSDaemon)
  } else {
    button.addEventListener('click', stopIPFSDaemon)
  }
}

function startIPFSDaemon () {
  sendCommandToIPFSDaemon('start')
  this.innerHTML = 'Starting...'
  this.setAttribute('disabled', 'disabled')
}

function stopIPFSDaemon () {
  sendCommandToIPFSDaemon('stop')
  this.innerHTML = 'Stopping...'
  this.setAttribute('disabled', 'disabled')
}

function getIPFSWebUIAddress () {
  const setIPFSWebUILink = function (resp) {
    document.getElementById('webui').setAttribute('href', 'http://' + resp)
  }
  const fail = function () { console.log('fail') }
  const err = function () { console.log('err') }
  makeAnAJAXRequest('/ipwbconfig/openEndedPlaceHolder', setIPFSWebUILink, fail, err)
}

function updateIPFSDaemonButtonUI () {
  window.setTimeout(function () {
    document.location.reload(true)
  }, 4000)
}

function sendCommandToIPFSDaemon (cmd) {
  const failFunction = function () { console.log('Comm w/ ipfs daemon failed.') }
  const errFunction = function () { console.log('Error talking to ipfs daemon.') }
  makeAnAJAXRequest('/ipfsdaemon/' + cmd, updateIPFSDaemonButtonUI,
    failFunction, errFunction)
}

function makeAnAJAXRequest (address, successFunction, failFunction, errorFunction) {
  let xmlhttp = new XMLHttpRequest()

  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState === XMLHttpRequest.DONE) {
      if (xmlhttp.status === 200) {
        successFunction(xmlhttp.responseText)
      } else if (xmlhttp.status === 400) {
        failFunction()
      } else {
        errorFunction()
      }
    }
  }

  xmlhttp.open('GET', address, true)
  xmlhttp.send()
}

function injectIPWBJS () {
  registerServiceWorker()
}

function getServiceWorkerVersion () {
  return fetch(self.location.href)
    .then(function (resp) {
      return Promise.resolve(resp.headers.get('Server').split('/')[1])
    })
}

function reinstallServiceWorker () {
  console.log('Deleting old serviceWorker')
  deleteServiceWorker()
  document.getElementById('serviceWorkerVersion').innerHTML = 'Updating...'
  installServiceWorker()
  updateServiceWorkerVersionUI()
}

function deleteServiceWorker () {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    for (let registration of registrations) {
      registration.unregister()
    }
  })
}

function updateServiceWorkerVersionUI () {
  getServiceWorkerVersion().then(function (resp) {
    console.log('updating to ...' + resp)
    document.getElementById('serviceWorkerVersion').innerHTML = 'ver. ' + resp
  })
}

function installServiceWorker () {
  let newInstallation = false

  if (navigator.serviceWorker.controller === null) { // Ideally we would use serviceWorker.getRegistration
    newInstallation = true
  }

  navigator.serviceWorker.register('/ipwbassets/serviceWorker.js', {scope: '/'}).then(
    function (registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope)
    }).catch(function (err) {
    console.log('ServiceWorker registration failed: ', err)
  }).then(function (rr) {
    const dt = document.location.href.split('/')[3]
    const viewingMemento = dt.length === 14 && parseInt(dt, 10) + '' === dt

    // Reload the page with processing by the newly installed Service Worker
    if (newInstallation && viewingMemento) {
      document.location.reload()
    }
  })
}

function registerServiceWorker () {
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', installServiceWorker)
  } else {
    console.log('Browser does not support Service Worker.')
  }
}

function serviceWorkerUpToDate () {

}

function updateServiceWorker () {

}

function reloadPageFromServiceWorker () {
  console.log('reloading page from serviceWorker!')
}
<commit_msg>Regain sort order in main replay URI list. Closes #562<commit_after>function handleSubmit () {
  let val = document.getElementById('url').value
  if (val) {
    document.location += 'memento/*/' + val
  }
}

function shortestFirst (a, b) {
  return a.length - b.length
}

function hideURIs () {
  document.getElementById('uris').classList.add('hidden')
  document.getElementById('memCountListLink').classList.remove('activated')
  window.localStorage.setItem('showURIs', 'false')
}

function addURIListToDOM () {
  let ul = document.getElementById('uriList')
  const uriKeys = Object.keys(uris).sort(shortestFirst)

  uriKeys.forEach(urir => {
    uris[urir].forEach(function (memento) {
      let li = document.createElement('li')
      let a = document.createElement('a')
      a.href = 'memento/' + memento['datetime'] + '/' + urir
      a.appendChild(document.createTextNode(urir))
      dt = document.createTextNode(' (' + memento['datetime'] + ')')

      li.appendChild(a)
      li.appendChild(dt)

      li.setAttribute('data-mime', memento['mime'])
      li.setAttribute('data-status', memento['status'])

      const isHTML = memento['mime'].toLowerCase().startsWith('text/html')
      const isARedirect = memento['status'][0] === '3'
      if (isHTML && !isARedirect) {
        li.setAttribute('data-display', 'default')
      }
      ul.appendChild(li)
    })
  })
}

function showURIs () {
  if (document.getElementById('uriList').childNodes.length === 0) {
    addURIListToDOM() // Prevent multiple adds of the URI list to the DOM
  }

  document.getElementById('memCountListLink').className = ['activated']
  document.getElementById('uris').classList.remove('hidden')
  setPlurality()
  setShowAllButtonStatus()

  setUIExpandedState(uris)
  // Maintain visible state of URI display for future retrieval
  window.localStorage.setItem('showURIs', 'true')
}

function setUIExpandedState (urisObj) {
  const urisHash = calculateURIsHash(urisObj)
  setURIsHash(urisHash)
}

function calculateURIsHash (urisObj) {
  return JSON.stringify(urisObj).hashCode()
}

function getURIsHash () {
  return window.localStorage.getItem('urisHash')
}

function setURIsHash (hashIn) {
  return window.localStorage.setItem('urisHash', hashIn)
}

String.prototype.hashCode = function () {
  let hash = 0
  let i
  let chr
  if (this.length === 0) {
    return hash
  }
  for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i)
    hash = ((hash << 5) - hash) + chr
    hash |= 0 // Convert to 32bit integer
  }
  return hash
}

function toggleURIDisplay () {
  if (window.localStorage.getItem('showURIs') === 'true') {
    hideURIs()
  } else {
    showURIs()
  }
}

function addEventListeners () {
  let target = document.getElementById('memCountListLink')
  target.addEventListener('click', toggleURIDisplay, false)

  let showAllInListingButton = document.getElementById('showEmbeddedURI')
  showAllInListingButton.onclick = function showAllURIs () {
    const uriList = document.getElementById('uriList')
    if (this.innerHTML === this.dataset.defaultvalue) {
      this.innerHTML = this.dataset.activatedvalue
      uriList.classList.add('forceDisplay')
    } else {
      this.innerHTML = this.dataset.defaultvalue
      uriList.classList.remove('forceDisplay')
    }
  }

  getIPFSWebUIAddress()
  updateServiceWorkerVersionUI()

  let reinstallServiceWorkerButton = document.getElementById('reinstallServiceWorker')
  reinstallServiceWorkerButton.onclick = reinstallServiceWorker

  setShowURIsVisibility()
}

function setShowURIsVisibility () {
  const previousHash = getURIsHash() + ''
  const newHash = calculateURIsHash(uris) + ''

  if (window.localStorage.getItem('showURIs') && previousHash === newHash) {
    showURIs()
  } else {
    hideURIs()
  }
}

function setPlurality () {
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML

  if (htmlFilesPlurality === '1') {
    document.getElementById('htmlPagesPlurality').classList.add('hidden')
  }
}

function setShowAllButtonStatus () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML
  if (urimCount === htmlFilesPlurality) {
    document.getElementById('showEmbeddedURI').setAttribute('disabled', 'disabled')
  }
}

function assignStatusButtonHandlers () {
  let button = document.getElementsByTagName('button')[0]
  if (button.innerHTML === 'Start') {
    button.addEventListener('click', startIPFSDaemon)
  } else {
    button.addEventListener('click', stopIPFSDaemon)
  }
}

function startIPFSDaemon () {
  sendCommandToIPFSDaemon('start')
  this.innerHTML = 'Starting...'
  this.setAttribute('disabled', 'disabled')
}

function stopIPFSDaemon () {
  sendCommandToIPFSDaemon('stop')
  this.innerHTML = 'Stopping...'
  this.setAttribute('disabled', 'disabled')
}

function getIPFSWebUIAddress () {
  const setIPFSWebUILink = function (resp) {
    document.getElementById('webui').setAttribute('href', 'http://' + resp)
  }
  const fail = function () { console.log('fail') }
  const err = function () { console.log('err') }
  makeAnAJAXRequest('/ipwbconfig/openEndedPlaceHolder', setIPFSWebUILink, fail, err)
}

function updateIPFSDaemonButtonUI () {
  window.setTimeout(function () {
    document.location.reload(true)
  }, 4000)
}

function sendCommandToIPFSDaemon (cmd) {
  const failFunction = function () { console.log('Comm w/ ipfs daemon failed.') }
  const errFunction = function () { console.log('Error talking to ipfs daemon.') }
  makeAnAJAXRequest('/ipfsdaemon/' + cmd, updateIPFSDaemonButtonUI,
    failFunction, errFunction)
}

function makeAnAJAXRequest (address, successFunction, failFunction, errorFunction) {
  let xmlhttp = new XMLHttpRequest()

  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState === XMLHttpRequest.DONE) {
      if (xmlhttp.status === 200) {
        successFunction(xmlhttp.responseText)
      } else if (xmlhttp.status === 400) {
        failFunction()
      } else {
        errorFunction()
      }
    }
  }

  xmlhttp.open('GET', address, true)
  xmlhttp.send()
}

function injectIPWBJS () {
  registerServiceWorker()
}

function getServiceWorkerVersion () {
  return fetch(self.location.href)
    .then(function (resp) {
      return Promise.resolve(resp.headers.get('Server').split('/')[1])
    })
}

function reinstallServiceWorker () {
  console.log('Deleting old serviceWorker')
  deleteServiceWorker()
  document.getElementById('serviceWorkerVersion').innerHTML = 'Updating...'
  installServiceWorker()
  updateServiceWorkerVersionUI()
}

function deleteServiceWorker () {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    for (let registration of registrations) {
      registration.unregister()
    }
  })
}

function updateServiceWorkerVersionUI () {
  getServiceWorkerVersion().then(function (resp) {
    console.log('updating to ...' + resp)
    document.getElementById('serviceWorkerVersion').innerHTML = 'ver. ' + resp
  })
}

function installServiceWorker () {
  let newInstallation = false

  if (navigator.serviceWorker.controller === null) { // Ideally we would use serviceWorker.getRegistration
    newInstallation = true
  }

  navigator.serviceWorker.register('/ipwbassets/serviceWorker.js', {scope: '/'}).then(
    function (registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope)
    }).catch(function (err) {
    console.log('ServiceWorker registration failed: ', err)
  }).then(function (rr) {
    const dt = document.location.href.split('/')[3]
    const viewingMemento = dt.length === 14 && parseInt(dt, 10) + '' === dt

    // Reload the page with processing by the newly installed Service Worker
    if (newInstallation && viewingMemento) {
      document.location.reload()
    }
  })
}

function registerServiceWorker () {
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', installServiceWorker)
  } else {
    console.log('Browser does not support Service Worker.')
  }
}

function serviceWorkerUpToDate () {

}

function updateServiceWorker () {

}

function reloadPageFromServiceWorker () {
  console.log('reloading page from serviceWorker!')
}
<|endoftext|>


<commit_before>module.exports = {
  primarySidebar: {
    Docs: [
      'getting-started',
      'how-it-works',
      'configuration',
      'imports',
      'integrations',
      'shebang',
      'interpreting-errors',
    ],
  },
};
<commit_msg>Update sidebars.js<commit_after>module.exports = {
  primarySidebar: {
    Docs: [
      'getting-started',
      'how-it-works',
      'configuration',
      'imports',
      'integrations',
      'shebang',
      'errors',
    ],
  },
};
<|endoftext|>


<commit_before>/*
var ipv_activityType="1";
var ipv_activityName="Run";
var ipv_workoutActivityID="23t3eoKlRcm6WbobHNJmRQ==";

https://motoactv.com/data/workoutDetail.json?workoutActivityId=23t3eoKlRcm6WbobHNJmRQ%3D%3D&activity=1&r=0.8102906856220216

		*/

function getShareUrl(id, callback) {

			var postData = {
				workoutActivityId: id
			};

			$.ajax({
				url: "/sharing/shareWorkout.json",
				type: 'POST',
				data: postData,
				dataType: 'json',
				success: function(json) {
					$("#socialWaitDialog").dialog("close");

					if (json && ((typeof json.code == "undefined") || (json.code > -1))) {
						var urlToShare = json.short_url;

						callback(urlToShare);
					}
					else {
						alert("Error getting share url");
					}
				}
			});
		};

var workoutId = "23t3eoKlRcm6WbobHNJmRQ==";
var detailsUrl = "https://motoactv.com/data/workoutDetail.json?workoutActivityId=";

	var url = detailsUrl + encodeURI( workoutId );
	//alert(url);
	try{
	$.ajax({
		url: url,
		data: { username: encodeURI('motorola@redune.com') },
		success: function(data){

			var name = data.journaldata.journalname;
			var notes = data.journaldata.journalnotes;

			var distance = data.summary.DISTANCE;

			var startTime = data.summary.STARTTIME;
			var endTime = data.summary.ENDTIME;

			var elapsedTime = endTime - startTime;

			getShareUrl(workoutId, function(url){
				alert(url);
				window.open(url);
			});

		},
		error: function(data, status, errorThrown){
			alert(data);
		}
	});
	}catch(ex){
		alert(ex);
	}

<commit_msg>start building workout object<commit_after>/*
var ipv_activityType="1";
var ipv_activityName="Run";
var ipv_workoutActivityID="23t3eoKlRcm6WbobHNJmRQ==";

https://motoactv.com/data/workoutDetail.json?workoutActivityId=23t3eoKlRcm6WbobHNJmRQ%3D%3D&activity=1&r=0.8102906856220216

		*/

function formatTime(timestamp){
	// create a new javascript Date object based on the timestamp

	var date = new Date(timestamp);

	var formattedTime =  date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "T" + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + "Z";

	return formattedTime;
}

function getShareUrl(id, callback) {

	var postData = {
		workoutActivityId: id
	};

	$.ajax({
		url: "/sharing/shareWorkout.json",
		type: 'POST',
		data: postData,
		dataType: 'json',
		success: function(json) {
			$("#socialWaitDialog").dialog("close");

			if (json && ((typeof json.code == "undefined") || (json.code > -1))) {
				var urlToShare = json.short_url;

				callback(urlToShare);

			}
			else {
				alert("Error getting share url");
			}
		}
	});
};

var workoutId = "23t3eoKlRcm6WbobHNJmRQ==";
var detailsUrl = "https://motoactv.com/data/workoutDetail.json?workoutActivityId=";

	var url = detailsUrl + encodeURI( workoutId );
	//alert(url);
	try{
	$.ajax({
		url: url,
		data: { username: encodeURI('motorola@redune.com') },
		success: function(data){

			var startTime = data.summary.STARTTIME;
			var endTime = data.summary.ENDTIME;

			var entry = {
				lat: data.route[0].LATITUDE,
				lon: data.route[0].LONGITUDE,
				workout: {
					activity_type: "running",
					completed_at: formatTime( endTime ),
					distance: {
						value: endTime,
						units: "kilometers"
					},
					duration: ( endTime - startTime ) / 1000,
					calories: data.summary.CALORIEBURN,
					title: data.journaldata.journalname
				}
			};

			alert(entry.workout.title);
				/*

workout[title], string (optional)
optional title for a workout
workout[route_id], integer (optional)
the id of the route associated with this workout (see route docs)
*/

			var name = ;
			var notes = data.journaldata.journalnotes;

			//var endTime = data.summary.ENDTIME;

			var elapsedTime = endTime - startTime;

			getShareUrl(workoutId, function(url){
				alert(url);
			});

		},
		error: function(data, status, errorThrown){
			alert(data);
		}
	});
	}catch(ex){
		alert(ex);
	}

<|endoftext|>


<commit_before>var Keycloak = function (options) {
    options = options || {};

    if (!(this instanceof Keycloak)) {
        return new Keycloak(options);
    }

    var kc = this;

    if (!options.url) {
        var scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            if (scripts[i].src.match(/.*keycloak\.js/)) {
                options.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/auth/js/keycloak.js'));
                break;
            }
        }
    }

    if (!options.url) {
        throw 'url missing';
    }

    if (!options.realm) {
        throw 'realm missing';
    }

    if (!options.clientId) {
        throw 'clientId missing';
    }

    if (!options.clientSecret) {
        throw 'clientSecret missing';
    }

    kc.init = function (successCallback, errorCallback) {
        if (window.oauth.callback) {
            delete sessionStorage.oauthToken;
            processCallback(successCallback, errorCallback);
        } else if (options.token) {
            kc.setToken(options.token, successCallback);
        } else if (sessionStorage.oauthToken) {
            kc.setToken(sessionStorage.oauthToken, successCallback);
        } else if (options.onload) {
            switch (options.onload) {
                case 'login-required' :
                    window.location = kc.createLoginUrl(true);
                    break;
                case 'check-sso' :
                    window.location = kc.createLoginUrl(false);
                    break;
            }
        }
    }

    kc.login = function () {
        window.location.href = kc.createLoginUrl(true);
    }

    kc.logout = function () {
        kc.setToken(undefined);
        window.location.href = kc.createLogoutUrl();
    }

    kc.hasRealmRole = function (role) {
        var access = kc.realmAccess;
        return access && access.roles.indexOf(role) >= 0 || false;
    }

    kc.hasResourceRole = function (role, resource) {
        if (!kc.resourceAccess) {
            return false;
        }

        var access = kc.resourceAccess[resource || options.clientId];
        return access && access.roles.indexOf(role) >= 0 || false;
    }

    kc.loadUserProfile = function (success, error) {
        var url = kc.getRealmUrl() + '/account';
        var req = new XMLHttpRequest();
        req.open('GET', url, true);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Authorization', 'bearer ' + kc.token);

        req.onreadystatechange = function () {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    kc.profile = JSON.parse(req.responseText);
                    success && success(kc.profile)
                } else {
                    var response = { status: req.status, statusText: req.status };
                    if (req.responseText) {
                        response.data = JSON.parse(req.responseText);
                    }
                    error && error(response);
                }
            }
        }

        req.send();
    }

    /**
     * checks to make sure token is valid.  If it is, it calls successCallback with no parameters.
     * If it isn't valid, it tries to refresh the access token.  On successful refresh, it calls successCallback.
     *
     * @param successCallback
     * @param errorCallback
     */
    kc.onValidAccessToken = function(successCallback, errorCallback) {
        if (!kc.tokenParsed) {
            console.log('no token');
            errorCallback();
            return;
        }
        var currTime = new Date().getTime() / 1000;
        if (currTime > kc.tokenParsed['exp']) {
            if (!kc.refreshToken) {
                console.log('no refresh token');
                errorCallback();
                return;
            }
            console.log('calling refresh');
            var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
            var url = kc.getRealmUrl() + '/tokens/refresh';

            var req = new XMLHttpRequest();
            req.open('POST', url, true, options.clientId, options.clientSecret);
            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

            req.onreadystatechange = function () {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        console.log('Refresh Success');
                        var tokenResponse = JSON.parse(req.responseText);
                        kc.refreshToken = tokenResponse['refresh_token'];
                        kc.setToken(tokenResponse['access_token'], successCallback);
                    } else {
                        console.log('error on refresh HTTP invoke: ' + req.status);
                        errorCallback && errorCallback({ authenticated: false, status: req.status, statusText: req.statusText });
                    }
                }
            };
            req.send(params);
        } else {
            console.log('Token is still valid');
            successCallback();
        }

    }

    kc.getRealmUrl = function() {
        return options.url + '/auth/rest/realms/' + encodeURIComponent(options.realm);
    }

    function processCallback(successCallback, errorCallback) {
        var code = window.oauth.code;
        var error = window.oauth.error;
        var prompt = window.oauth.prompt;

        if (code) {
            var params = 'code=' + code;
            var url = kc.getRealmUrl() + '/tokens/access/codes';

            var req = new XMLHttpRequest();
            req.open('POST', url, true);
            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            req.setRequestHeader('Authorization', 'Basic ' + btoa(options.clientId + ':' + options.clientSecret));
            req.withCredentials = true;

            req.onreadystatechange = function () {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        var tokenResponse = JSON.parse(req.responseText);
                        kc.refreshToken = tokenResponse['refresh_token'];
                        kc.setToken(tokenResponse['access_token'], successCallback);
                    } else {
                        errorCallback && errorCallback({ authenticated: false, status: req.status, statusText: req.statusText });
                    }
                }
            };

            req.send(params);
        } else if (error) {
            if (prompt != 'none') {
                setTimeout(function() {
                    errorCallback && errorCallback({  authenticated: false, error: error })
                }, 0);
            }
        }
    }

    kc.setToken = function(token, successCallback) {
        if (token) {
            sessionStorage.oauthToken = token;
            window.oauth.token = token;
            kc.token = token;

            kc.tokenParsed = JSON.parse(atob(token.split('.')[1]));
            kc.authenticated = true;
            kc.subject = kc.tokenParsed.sub;
            kc.realmAccess = kc.tokenParsed.realm_access;
            kc.resourceAccess = kc.tokenParsed.resource_access;

            setTimeout(function() {
                successCallback && successCallback({ authenticated: kc.authenticated, subject: kc.subject });
            }, 0);
        } else {
            delete sessionStorage.oauthToken;
            delete window.oauth.token;
            delete kc.token;
        }
    }

    kc.createLoginUrl = function(prompt) {
        var state = createUUID();

        sessionStorage.oauthState = state;
        var url = kc.getRealmUrl()
            + '/tokens/login'
            + '?client_id=' + encodeURIComponent(options.clientId)
            + '&redirect_uri=' + getEncodedRedirectUri()
            + '&state=' + encodeURIComponent(state)
            + '&response_type=code';

        if (prompt == false) {
            url += '&prompt=none';
        }

        return url;
    }

    kc.createLogoutUrl = function() {
        var url = kc.getRealmUrl()
            + '/tokens/logout'
            + '?redirect_uri=' + getEncodedRedirectUri();
        return url;
    }

    function getEncodedRedirectUri() {
        var url;
        if (options.redirectUri) {
            url = options.redirectUri;
        } else {
            url = (location.protocol + '//' + location.hostname + (location.port && (':' + location.port)) + location.pathname);
            if (location.hash) {
                url += '?redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
            }
        }
        return encodeURI(url);
    }

    function createUUID() {
        var s = [];
        var hexDigits = '0123456789abcdef';
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = '4';
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        s[8] = s[13] = s[18] = s[23] = '-';
        var uuid = s.join('');
        return uuid;
    }
}

window.oauth = (function () {
    var oauth = {};

    var params = window.location.search.substring(1).split('&');
    for (var i = 0; i < params.length; i++) {
        var p = params[i].split('=');
        switch (decodeURIComponent(p[0])) {
            case 'code':
                oauth.code = p[1];
                break;
            case 'error':
                oauth.error = p[1];
                break;
            case 'state':
                oauth.state = decodeURIComponent(p[1]);
                break;
            case 'redirect_fragment':
                oauth.fragment = decodeURIComponent(p[1]);
                break;
            case 'prompt':
                oauth.prompt = p[1];
                break;
        }
    }

    if (oauth.state && oauth.state == sessionStorage.oauthState) {
        oauth.callback = true;
        delete sessionStorage.oauthState;
    } else {
        oauth.callback = false;
    }

    if (oauth.callback) {
        window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (oauth.fragment ? '#' + oauth.fragment : ''));
    } else if (oauth.fragment) {
        window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (oauth.fragment ? '#' + oauth.fragment : ''));
    }

    return oauth;
}());<commit_msg>Remove clientSecret required in JS lib, and removed storing token to sessionStore<commit_after>var Keycloak = function (options) {
    options = options || {};

    if (!(this instanceof Keycloak)) {
        return new Keycloak(options);
    }

    var kc = this;

    if (!options.url) {
        var scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            if (scripts[i].src.match(/.*keycloak\.js/)) {
                options.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/auth/js/keycloak.js'));
                break;
            }
        }
    }

    if (!options.url) {
        throw 'url missing';
    }

    if (!options.realm) {
        throw 'realm missing';
    }

    if (!options.clientId) {
        throw 'clientId missing';
    }

    kc.init = function (successCallback, errorCallback) {
        if (window.oauth.callback) {
            processCallback(successCallback, errorCallback);
        } else if (options.token) {
            kc.setToken(options.token, successCallback);
        } else if (options.onload) {
            switch (options.onload) {
                case 'login-required' :
                    window.location = kc.createLoginUrl(true);
                    break;
                case 'check-sso' :
                    window.location = kc.createLoginUrl(false);
                    break;
            }
        }
    }

    kc.login = function () {
        window.location.href = kc.createLoginUrl(true);
    }

    kc.logout = function () {
        kc.setToken(undefined);
        window.location.href = kc.createLogoutUrl();
    }

    kc.hasRealmRole = function (role) {
        var access = kc.realmAccess;
        return access && access.roles.indexOf(role) >= 0 || false;
    }

    kc.hasResourceRole = function (role, resource) {
        if (!kc.resourceAccess) {
            return false;
        }

        var access = kc.resourceAccess[resource || options.clientId];
        return access && access.roles.indexOf(role) >= 0 || false;
    }

    kc.loadUserProfile = function (success, error) {
        var url = kc.getRealmUrl() + '/account';
        var req = new XMLHttpRequest();
        req.open('GET', url, true);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Authorization', 'bearer ' + kc.token);

        req.onreadystatechange = function () {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    kc.profile = JSON.parse(req.responseText);
                    success && success(kc.profile)
                } else {
                    var response = { status: req.status, statusText: req.status };
                    if (req.responseText) {
                        response.data = JSON.parse(req.responseText);
                    }
                    error && error(response);
                }
            }
        }

        req.send();
    }

    /**
     * checks to make sure token is valid.  If it is, it calls successCallback with no parameters.
     * If it isn't valid, it tries to refresh the access token.  On successful refresh, it calls successCallback.
     *
     * @param successCallback
     * @param errorCallback
     */
    kc.onValidAccessToken = function(successCallback, errorCallback) {
        if (!kc.tokenParsed) {
            console.log('no token');
            errorCallback();
            return;
        }
        var currTime = new Date().getTime() / 1000;
        if (currTime > kc.tokenParsed['exp']) {
            if (!kc.refreshToken) {
                console.log('no refresh token');
                errorCallback();
                return;
            }
            console.log('calling refresh');
            var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
            var url = kc.getRealmUrl() + '/tokens/refresh';

            var req = new XMLHttpRequest();
            req.open('POST', url, true, options.clientId, options.clientSecret);
            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

            req.onreadystatechange = function () {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        console.log('Refresh Success');
                        var tokenResponse = JSON.parse(req.responseText);
                        kc.refreshToken = tokenResponse['refresh_token'];
                        kc.setToken(tokenResponse['access_token'], successCallback);
                    } else {
                        console.log('error on refresh HTTP invoke: ' + req.status);
                        errorCallback && errorCallback({ authenticated: false, status: req.status, statusText: req.statusText });
                    }
                }
            };
            req.send(params);
        } else {
            console.log('Token is still valid');
            successCallback();
        }

    }

    kc.getRealmUrl = function() {
        return options.url + '/auth/rest/realms/' + encodeURIComponent(options.realm);
    }

    function processCallback(successCallback, errorCallback) {
        var code = window.oauth.code;
        var error = window.oauth.error;
        var prompt = window.oauth.prompt;

        if (code) {
            var params = 'code=' + code;
            var url = kc.getRealmUrl() + '/tokens/access/codes';

            var req = new XMLHttpRequest();
            req.open('POST', url, true);
            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

            if (options.clientId && options.clientSecret) {
                req.setRequestHeader('Authorization', 'Basic ' + btoa(options.clientId + ':' + options.clientSecret));
            } else {
                params += '&client_id=' + encodeURIComponent(options.clientId);
            }

            req.withCredentials = true;

            req.onreadystatechange = function () {
                if (req.readyState == 4) {
                    if (req.status == 200) {
                        var tokenResponse = JSON.parse(req.responseText);
                        kc.refreshToken = tokenResponse['refresh_token'];
                        kc.setToken(tokenResponse['access_token'], successCallback);
                    } else {
                        errorCallback && errorCallback({ authenticated: false, status: req.status, statusText: req.statusText });
                    }
                }
            };

            req.send(params);
        } else if (error) {
            if (prompt != 'none') {
                setTimeout(function() {
                    errorCallback && errorCallback({  authenticated: false, error: error })
                }, 0);
            }
        }
    }

    kc.setToken = function(token, successCallback) {
        if (token) {
            window.oauth.token = token;
            kc.token = token;

            kc.tokenParsed = JSON.parse(atob(token.split('.')[1]));
            kc.authenticated = true;
            kc.subject = kc.tokenParsed.sub;
            kc.realmAccess = kc.tokenParsed.realm_access;
            kc.resourceAccess = kc.tokenParsed.resource_access;

            setTimeout(function() {
                successCallback && successCallback({ authenticated: kc.authenticated, subject: kc.subject });
            }, 0);
        } else {
            delete window.oauth.token;
            delete kc.token;
        }
    }

    kc.createLoginUrl = function(prompt) {
        var state = createUUID();

        sessionStorage.oauthState = state;
        var url = kc.getRealmUrl()
            + '/tokens/login'
            + '?client_id=' + encodeURIComponent(options.clientId)
            + '&redirect_uri=' + getEncodedRedirectUri()
            + '&state=' + encodeURIComponent(state)
            + '&response_type=code';

        if (prompt == false) {
            url += '&prompt=none';
        }

        return url;
    }

    kc.createLogoutUrl = function() {
        var url = kc.getRealmUrl()
            + '/tokens/logout'
            + '?redirect_uri=' + getEncodedRedirectUri();
        return url;
    }

    function getEncodedRedirectUri() {
        var url;
        if (options.redirectUri) {
            url = options.redirectUri;
        } else {
            url = (location.protocol + '//' + location.hostname + (location.port && (':' + location.port)) + location.pathname);
            if (location.hash) {
                url += '?redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
            }
        }
        return encodeURI(url);
    }

    function createUUID() {
        var s = [];
        var hexDigits = '0123456789abcdef';
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = '4';
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
        s[8] = s[13] = s[18] = s[23] = '-';
        var uuid = s.join('');
        return uuid;
    }
}

window.oauth = (function () {
    var oauth = {};

    var params = window.location.search.substring(1).split('&');
    for (var i = 0; i < params.length; i++) {
        var p = params[i].split('=');
        switch (decodeURIComponent(p[0])) {
            case 'code':
                oauth.code = p[1];
                break;
            case 'error':
                oauth.error = p[1];
                break;
            case 'state':
                oauth.state = decodeURIComponent(p[1]);
                break;
            case 'redirect_fragment':
                oauth.fragment = decodeURIComponent(p[1]);
                break;
            case 'prompt':
                oauth.prompt = p[1];
                break;
        }
    }

    if (oauth.state && oauth.state == sessionStorage.oauthState) {
        oauth.callback = true;
        delete sessionStorage.oauthState;
    } else {
        oauth.callback = false;
    }

    if (oauth.callback) {
        window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (oauth.fragment ? '#' + oauth.fragment : ''));
    } else if (oauth.fragment) {
        window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (oauth.fragment ? '#' + oauth.fragment : ''));
    }

    return oauth;
}());<|endoftext|>


<commit_before>/* eslint-disable react/destructuring-assignment */
import React from 'react';
import { action } from '@storybook/addon-actions';
import { Button } from '@storybook/react/demo';

import Container from '../components/Container';

const InfoButton = () => (

     Show Info

);

export default {
  title: 'Button',
  component: Button,
};

export const Story1 = () => <Button onClick={action('clicked', { depth: 1 })}>Hello Button</Button>;
Story1.story = {
  name: 'with text',
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};

export const Story2 = () => (
  <Button onClick={action('clicked')}>

      😀 😎 👍 💯

  </Button>
);
Story2.story = {
  name: 'with some emoji',
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};
<commit_msg>CLEANUP<commit_after>/* eslint-disable react/destructuring-assignment */
import React from 'react';
import { action } from '@storybook/addon-actions';
import { Button } from '@storybook/react/demo';

export default {
  title: 'Button',
  component: Button,
};

export const Story1 = () => <Button onClick={action('clicked', { depth: 1 })}>Hello Button</Button>;
Story1.story = {
  name: 'with text',
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};

export const Story2 = () => (
  <Button onClick={action('clicked')}>

      😀 😎 👍 💯

  </Button>
);
Story2.story = {
  name: 'with some emoji',
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};
<|endoftext|>


<commit_before>describe('direcive.c-add-element-directive', function () {
  beforeEach(module('webApp'));
  var directive, scope, fakeModel, fakeInputToAdd = null;

  beforeEach(inject(function ($httpBackend, $rootScope, $compile) {
    $httpBackend.when('GET', 'languages/en-US.json')
      .respond({});
    var fakeIconClass = "'fake class'";
    var fakeText = "'fake text'";
    var fakeDataQA = "'fake data QA'";
    var fakePattern = "[a-zA-Z0-9]*";
    var fakeModelError = {"text": ""};
    var fakePlaceholder = "'fake placeholder'";
    fakeInputToAdd = "fake input to add";
    fakeModel = [];
    $httpBackend.when('GET', 'templates/components/c-add-element.tpl.html')
      .respond("

");

    scope = $rootScope.$new();

    scope.model = fakeModel;
    directive = angular.element(' <c-add-element model="model"' +
      ' icon-class="' + fakeIconClass + '" type="' + fakeText + '" data-qa="' + fakeDataQA + '" data-pattern="\'' + fakePattern + '\'"' +
      '  data-error="' + fakeModelError.text + "\"" +
      '  data-placeholder="' + fakePlaceholder + '">      </c-add-element>');

    directive = $compile(directive)(scope);
    scope.$digest();
    $httpBackend.flush();
  }));

  describe("should be able to add the new input to the array introduced as model", function () {
    var isolatedScope = null;

    describe("if the input to add has been fill out by user", function () {
      beforeEach(function () {
        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = "fake input to add";
      });
      it("it is added when user press the enter key", function () {
        var fakeEvent = {
          "keyCode": '13', preventDefault: function () {
          }
        };
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(1);

        fakeEvent.keyCode = '15'; // key different to enter key
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(1); // input is not added
      });

      it("it is added when user press a button which has been implemented to add the input", function () {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        var previousLength = isolatedScope.model.length;
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(previousLength + 1);
      });

      it("it is not added if the model array contains the element already", inject(function ($compile) {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = fakeInputToAdd;

        fakeModel.push(fakeInputToAdd);
        var previousLength = fakeModel.length;

        // user tries to add the same element again
        isolatedScope.addInput(fakeEvent);

        expect(isolatedScope.model.length).toBe(previousLength); // the same length because element has not been added
      }));

      it("it is added if the model array does not contain the element already", inject(function ($compile) {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        var newInputToAdd = "new input";

        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = fakeInputToAdd;
        fakeModel.push(newInputToAdd);
        var previousLength = fakeModel.length;

        // user tries to add another element
        isolatedScope.addInput(fakeEvent);

        expect(isolatedScope.model.length).toBe(previousLength+1); // the same length because element has not been added
      }));
    });
  });

});
<commit_msg>refactor(c-add-element-directive): Clean unit tests of c-add-element directive<commit_after>describe('direcive.c-add-element-directive', function () {
  beforeEach(module('webApp'));
  var directive, scope, fakeModel, fakeInputToAdd = null;

  beforeEach(inject(function ($httpBackend, $rootScope, $compile) {
    $httpBackend.when('GET', 'languages/en-US.json')
      .respond({});
    var fakeIconClass = "'fake class'";
    var fakeText = "'fake text'";
    var fakeDataQA = "'fake data QA'";
    var fakePattern = "[a-zA-Z0-9]*";
    var fakeModelError = {"text": ""};
    var fakePlaceholder = "'fake placeholder'";
    fakeInputToAdd = "fake input to add";
    fakeModel = [];
    $httpBackend.when('GET', 'templates/components/c-add-element.tpl.html')
      .respond("

");

    scope = $rootScope.$new();

    scope.model = fakeModel;
    directive = angular.element(' <c-add-element model="model"' +
      ' icon-class="' + fakeIconClass + '" type="' + fakeText + '" data-qa="' + fakeDataQA + '" data-pattern="\'' + fakePattern + '\'"' +
      '  data-error="' + fakeModelError.text + "\"" +
      '  data-placeholder="' + fakePlaceholder + '">      </c-add-element>');

    directive = $compile(directive)(scope);
    scope.$digest();
    $httpBackend.flush();
  }));

  describe("should be able to add the new input to the array introduced as model", function () {
    var isolatedScope = null;

    describe("if the input to add has been fill out by user", function () {
      beforeEach(function () {
        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = "fake input to add";
      });
      it("it is added when user press the enter key", function () {
        var fakeEvent = {
          "keyCode": '13', preventDefault: function () {
          }
        };
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(1);

        fakeEvent.keyCode = '15'; // key different to enter key
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(1); // input is not added
      });

      it("it is added when user press a button which has been implemented to add the input", function () {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        var previousLength = isolatedScope.model.length;
        isolatedScope.addInput(fakeEvent);
        expect(isolatedScope.model.length).toBe(previousLength + 1);
      });

      it("it is not added if the model array contains the element already", function () {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = fakeInputToAdd;

        fakeModel.push(fakeInputToAdd);
        var previousLength = fakeModel.length;

        // user tries to add the same element again
        isolatedScope.addInput(fakeEvent);

        expect(isolatedScope.model.length).toBe(previousLength); // the same length because element has not been added
      });

      it("it is added if the model array does not contain the element already", function () {
        var fakeEvent = {
          "type": "click", preventDefault: function () {
          }
        };
        var newInputToAdd = "new input";

        isolatedScope = directive.isolateScope();
        isolatedScope.inputToAdd = fakeInputToAdd;
        fakeModel.push(newInputToAdd);
        var previousLength = fakeModel.length;

        // user tries to add another element
        isolatedScope.addInput(fakeEvent);

        expect(isolatedScope.model.length).toBe(previousLength+1); // the same length because element has not been added
      });
    });
  });

});
<|endoftext|>


<commit_before>var utils = require('../utils');
var layout = require('./layout');
var menu = require('./menu');
var widgets = require('./_commonWidgets');
var xhr = require('../xhr');
var i18n = require('../i18n');
var socket = require('../socket');

var nbPlaying = 0;

var seek = {};

seek.controller = function() {

  var hookId;
  var lobbySocket;

  window.analytics.trackView('Seek');

  var createHook = function() {
    xhr.seekGame().then(function(data) {
      hookId = data.hook.id;
    }, function(error) {
      utils.handleXhrError(error);
    });
  };

  xhr.lobby(true).then(function(data) {
    lobbySocket = socket.connectLobby(data.lobby.version, createHook, {
      redirect: function(data) {
        m.route('/play' + data.url);
      },
      n: function(n) {
        nbPlaying = n;
        m.redraw();
      },
      resync: function() {
        xhr.lobby().then(function(data) {
          if (lobbySocket) lobbySocket.setVersion(data.lobby.version);
        });
      }
    });
  });

  function cancel() {
    if (lobbySocket && hookId) lobbySocket.send('cancel', hookId);
    utils.backHistory();
  }

  document.addEventListener('backbutton', cancel, false);

  return {
    cancel: cancel,

    onunload: function() {
      if (lobbySocket) {
        lobbySocket.destroy();
        lobbySocket = null;
      }
      document.removeEventListener('backbutton', cancel, false);
    }
  };
};

seek.view = function(ctrl) {
  function overlays() {
    return [
      m('div.overlay', [
        m('div.overlay_content', [
          m('div', i18n('waitingForOpponent')),
          m('br'),
          m('div', i18n('nbConnectedPlayers', nbPlaying || '?')),
          m('br'),
          m('br'),
          m('button[data-icon=L]', {
            config: utils.ontouchend(ctrl.cancel),
          }, i18n('cancel'))
        ])
      ])
    ];
  }

  return layout.board(widgets.header, widgets.board, widgets.empty, menu.view, overlays);
};

module.exports = seek;
<commit_msg>fix #108 hopefuly<commit_after>var utils = require('../utils');
var layout = require('./layout');
var menu = require('./menu');
var widgets = require('./_commonWidgets');
var xhr = require('../xhr');
var i18n = require('../i18n');
var socket = require('../socket');

var nbPlaying = 0;

var seek = {};

seek.controller = function() {

  var hookId;
  var lobbySocket;

  window.analytics.trackView('Seek');

  var createHook = function() {
    if (hookId) return; // hook already created!
    xhr.seekGame().then(function(data) {
      hookId = data.hook.id;
    }, function(error) {
      utils.handleXhrError(error);
    });
  };

  xhr.lobby(true).then(function(data) {
    lobbySocket = socket.connectLobby(data.lobby.version, createHook, {
      redirect: function(data) {
        m.route('/play' + data.url);
      },
      n: function(n) {
        nbPlaying = n;
        m.redraw();
      },
      resync: function() {
        xhr.lobby().then(function(data) {
          if (lobbySocket) lobbySocket.setVersion(data.lobby.version);
        });
      }
    });
  });

  function cancel() {
    if (lobbySocket && hookId) lobbySocket.send('cancel', hookId);
    utils.backHistory();
  }

  document.addEventListener('backbutton', cancel, false);

  return {
    cancel: cancel,

    onunload: function() {
      if (lobbySocket) {
        lobbySocket.destroy();
        lobbySocket = null;
      }
      document.removeEventListener('backbutton', cancel, false);
    }
  };
};

seek.view = function(ctrl) {
  function overlays() {
    return [
      m('div.overlay', [
        m('div.overlay_content', [
          m('div', i18n('waitingForOpponent')),
          m('br'),
          m('div', i18n('nbConnectedPlayers', nbPlaying || '?')),
          m('br'),
          m('br'),
          m('button[data-icon=L]', {
            config: utils.ontouchend(ctrl.cancel),
          }, i18n('cancel'))
        ])
      ])
    ];
  }

  return layout.board(widgets.header, widgets.board, widgets.empty, menu.view, overlays);
};

module.exports = seek;
<|endoftext|>


<commit_before>/**
 * The app module is the glue for accessing the system. It creates all of the correct objects for database access
 * and logging.
 */
var util = require('util');
var EventEmitter = require('events').EventEmitter;

var app = function(config){
    "use strict";

    var app = {},
        cache = require('../utils/cache')(config.cache),
        log = require('solid-logger-js'),
        db = require('../db/database')(config.db),
        util = require('util'),
        self = this;

    log.init(config.logger);

    app.cache = cache;
    app.log = log;
    app.db = db;

    // Objects that require caching and logging need to get a reference to the application. Please put them here.
    app.db.init(app, function(err){
        if(err){
            self.emit('failed', err);
        }
        else {
            self.emit('ready', app);
        }
    });
};

util.inherits(app, EventEmitter);
module.exports = app;<commit_msg>Added crypto abilities to the core sdk<commit_after>/**
 * The app module is the glue for accessing the system. It creates all of the correct objects for database access
 * and logging.
 */
var util = require('util');
var EventEmitter = require('events').EventEmitter;

var app = function(config){
    "use strict";

    var app = {},
        cache = require('../utils/cache')(config.cache),
        log = require('solid-logger-js'),
        db = require('../db/database')(config.db),
        crypto = require('../utils/crypto')(config.crypto),
        util = require('util'),
        self = this;

    log.init(config.logger);

    app.cache = cache;
    app.log = log;
    app.db = db;
    app.crypto = crypto;

    // Objects that require caching and logging need to get a reference to the application. Please put them here.
    app.db.init(app, function(err){
        if(err){
            self.emit('failed', err);
        }
        else {
            self.emit('ready', app);
        }
    });
};

util.inherits(app, EventEmitter);
module.exports = app;<|endoftext|>


<commit_before>'use strict';

//////////////////////////////////////////////////////////////////////
// Text/board conversion. (not really UI-related, though)

// Receives an array of strings, where each string is one line.
// Returns a board.
function parse_text_input(lines) {
	var board = new Board();
	var terminator_count = {};
	for (var i = 0; i < lines.length; i++) {
		board.nodes[i] = [];
		for (var j = 0; j < lines[i].length; j++) {
			var c = lines[i][j];
			if (c == ' ' || c == '0') {
				board.nodes[i][j] = null;
			} else if (c >= '1' && c <= '4') {
				var num = parseInt(c, 10);
				board.nodes[i][j] = new Node(null, 2 * num);
			} else if (c >= 'a' && c <= 'z') {
				board.nodes[i][j] = new Node(c, 2);
			} else if (c >= 'A' && c <= 'Z') {
				board.nodes[i][j] = new Node(c.toLowerCase(), 1);
				board.terminators.push({'x': j, 'y': i});
				terminator_count[c] = (terminator_count[c] || 0) + 1;
			} else {
				board.errors.push('Invalid character: ' + c);
			}
		}
		if (j > board.width){
			board.width = j;
		}
	}
	board.height = i;

	if (board.width < 1 || board.height < 1) {
		board.errors.push('Empty board.');
	}

	if (terminator_count.length === 0) {
		board.errors.push('No terminator node was found.');
	}
	for (var i in terminator_count) {
		if (terminator_count[i] != 2) {
			board.errors.push('There are ' + terminator_count[i] + ' terminators of type ' + i + ', but only 2 are expected.');
		}
	}

	return board;
}

// Receives an already solved board.
// Returns a multi-line string with the solution in ASCII drawing.
function solution_to_text(board) {
	var sol = [];

	// Nodes.
	for (var i = 0; i < board.height; i++) {
		var line1 = [];
		var line2 = [];
		for (var j = 0; j < board.width; j++) {
			var name = ' ';
			var node = board.nodes[i][j];
			if (node) {
				if (node.max_edges === 1) {
					name = node.color.toUpperCase();
				} else {
					name = node.color || '*';
				}
			}
			line1.push(name, ' ');
			line2.push(' ', ' ');
		}
		sol.push(line1, line2);
	}

	// Edges.
	for (var i = 0; i < board.height; i++) {
		for (var j = 0; j < board.width; j++) {
			var node = board.nodes[i][j];
			if (node) {
				for (var k = 0; k < node.edges.length; k++) {
					var edge = node.edges[k];

					var x = j * 2 + edge.direction.dx;
					var y = i * 2 + edge.direction.dy;
					var c = edge.direction.char;
					sol[y][x] = c;
					// Edge color is ignored here.
				}
			}
		}
	}

	var ret = '';
	for (var i = 0; i < sol.length; i++) {
		ret += sol[i].join('') + '\n';
	}
	return ret;
}

//////////////////////////////////////////////////////////////////////
// DOM-related and UI-related manipulation.

function parse_board_from_input() {
	var puzzleinput = document.getElementById('puzzleinput');
	var lines = puzzleinput.value.split(/[\r\n]+/);
	var board = parse_text_input(lines);

	var messages = document.getElementById('messages');
	messages.textContent = board.errors.join('\n');
	messages.classList.remove('busy');

	return board;
}

function build_svg_from_board(board) {
	if (board.width < 1 || board.height < 1) {
		return;
	}

	var svgsolutioncontainer = document.getElementById('svgsolutioncontainer');

	var svg_code = '';

	var width = (board.width * 1.5 - 0.5);
	var height = (board.height * 1.5 - 0.5);
	svg_code += '<svg preserveAspectRatio="xMidYMin" viewBox="0 0 ' + width + ' ' + height + '">';

	var edge_colors = {
		's': '#fc1f20',
		'd': '#0086ff',
		't': '#ffa515',
		'p': '#009e00',
		'h': '#ca197d'
	};

	var revealrange = document.getElementById('revealrange');
	if (board.edge_count === 0) {
		revealrange.disabled = true;
	} else {
		revealrange.disabled = false;

		// Updating the slider to the new edge count.
		var is_reveal_slider_at_max = (revealrange.value === revealrange.max);
		revealrange.max = board.edge_count;
		if (is_reveal_slider_at_max) {
			// If value was already at maximum before, the user likely wants
			// the value at maximum again.
			revealrange.value = revealrange.max;
		}

		// Edge indexes being shuffled in a random order.
		var random_numbers = [];
		for (var i = 0; i < board.edge_count; i++) {
			random_numbers[i] = i;
		}
		shuffle(random_numbers);

		// Building the edges.
		for (var i = 0; i < board.height; i++) {
			for (var j = 0; j < board.width; j++) {
				var node = board.nodes[i][j];
				if (node) {
					for (var k = 0; k < node.edges.length; k++) {
						var edge = node.edges[k];
						svg_code += '<polyline ' +
							'class="edge" '+
							'id="edge' + random_numbers.pop() + '" ' +
							'stroke="' + edge_colors[edge.color] + '" ' +
							'marker-mid="url(#mid_arrow)"' +
							'points="' +
							'' + ((j                        ) * 1.5 + 0.5) + ',' + ((i                        ) * 1.5 + 0.5) + ' ' +
							'' + ((j + edge.direction.dx / 2) * 1.5 + 0.5) + ',' + ((i + edge.direction.dy / 2) * 1.5 + 0.5) + ' ' +
							'' + ((j + edge.direction.dx    ) * 1.5 + 0.5) + ',' + ((i + edge.direction.dy    ) * 1.5 + 0.5) + '" />';
					}
				}
			}
		}
	}

	// Building the nodes.
	for (var i = 0; i < board.height; i++) {
		for (var j = 0; j < board.width; j++) {
			var node = board.nodes[i][j];
			if (node) {
				var name = '';
				if (node.max_edges === 1) {
					name = node.color.toUpperCase();
				} else if (node.color) {
					name = node.color;
				} else {
					name = Math.floor(node.max_edges / 2) + '';
				}

				svg_code += '<use xlink:href="#node_' + name + '" x="' + (j * 1.5) + '" y="' + (i * 1.5) + '" width="1" height="1" />';
			}
		}
	}

	svg_code += '</svg>';
	svgsolutioncontainer.innerHTML = svg_code;

	reveal_edges(revealrange.value);
}

function reveal_edges(how_many) {
	var all_edges = document.querySelectorAll('#svgsolutioncontainer > svg .edge');
	for (var i = 0; i < all_edges.length; i++) {
		all_edges[i].style.display = 'none';
	}
	for (var i = 0; i < how_many; i++) {
		var edge = document.getElementById('edge' + i);
		if (edge) {
			edge.style.display = 'block';
		}
	}
}

//////////////////////////////////////////////////////////////////////
// Web Worker handling.

function interrupt_worker() {
	if (g_worker) {
		g_worker.terminate();
		g_worker = null;

		var solvebutton = document.getElementById('solvebutton');
		solvebutton.value = 'Solve it!';

		var messages = document.getElementById('messages');
		messages.classList.remove('busy');
	}
}

//////////////////////////////////////////////////////////////////////
// Event handling.

function puzzleinput_input_handler() {
	interrupt_worker();
	var board = parse_board_from_input();
	build_svg_from_board(board);
}

function solution_found_handler(e) {
	var solve_finish_date = new Date();
	var solve_time = solve_finish_date.getTime() - g_solve_start_date.getTime();
	solve_time = solve_time / 1000;  // Converting to seconds.

	interrupt_worker();

	var messages = document.getElementById('messages');
	var board = e.data;

	if (board.solution_found === true) {
		messages.textContent = 'Solution found after ' + solve_time.toFixed(1) + 's!';
	} else if (board.solution_found === false) {
		messages.textContent = 'No solution found after ' + solve_time.toFixed(1)+ 's. :(';
	} else {
		console.error('board.solution_found: ' + board.solution_found);
		messages.textContent = 'This should not have happened.';
	}
	messages.classList.remove('busy');

	//console.log(solution_to_text(board));
	build_svg_from_board(board);
}

function solvebutton_click_handler() {
	var messages = document.getElementById('messages');

	if (g_worker) {
		interrupt_worker();
		messages.textContent = 'Interrupted by user.';
	} else {
		var board = parse_board_from_input();

		if (board.errors.length === 0) {
			g_solve_start_date = new Date();

			// Run the solving algorithm in a background thread.
			g_worker = new Worker('algorithm.js');
			g_worker.addEventListener('message', solution_found_handler);
			g_worker.postMessage(board);

			var solvebutton = document.getElementById('solvebutton');
			solvebutton.value = 'Abort!';
			messages.textContent = 'Searching for a solution…';
			messages.classList.add('busy');
		}
	}
}

function revealrange_input_handler() {
	var revealrange = document.getElementById('revealrange');
	reveal_edges(revealrange.value);
}

function showarrowscheckbox_click_handler() {
	var showarrowscheckbox = document.getElementById('showarrowscheckbox');
	var svgsolutioncontainer = document.getElementById('svgsolutioncontainer');

	// Damn IE… Does not support toggle second argument.
	//svgsolutioncontainer.classList.toggle('hidearrows', !showarrowscheckbox.checked);
	if (showarrowscheckbox.checked) {
		svgsolutioncontainer.classList.remove('hidearrows');
	} else {
		svgsolutioncontainer.classList.add('hidearrows');
	}
}

function init() {
	var puzzleinput = document.getElementById('puzzleinput');
	puzzleinput.addEventListener('input', puzzleinput_input_handler);

	var solvebutton = document.getElementById('solvebutton');
	solvebutton.addEventListener('click', solvebutton_click_handler);

	var revealrange = document.getElementById('revealrange');
	revealrange.addEventListener('input', revealrange_input_handler);

	var showarrowscheckbox = document.getElementById('showarrowscheckbox');
	showarrowscheckbox.addEventListener('click', showarrowscheckbox_click_handler);

	puzzleinput_input_handler();
	showarrowscheckbox_click_handler();

	// Preload this file.
	var tmp_worker = new Worker('algorithm.js');
	tmp_worker.terminate();
}

// Global var pointing to the background thread.
var g_worker = null;
// Date object to measure the algorithm time.
var g_solve_start_date = null;

// This script should be included with "defer" attribute.
init();
<commit_msg>Rejecting characters that are not available in the SVG rendering.<commit_after>'use strict';

//////////////////////////////////////////////////////////////////////
// Text/board conversion. (not really UI-related, though)

// Receives an array of strings, where each string is one line.
// Returns a board.
function parse_text_input(lines) {
	var board = new Board();
	var terminator_count = {};
	for (var i = 0; i < lines.length; i++) {
		board.nodes[i] = [];
		for (var j = 0; j < lines[i].length; j++) {
			var c = lines[i][j];
			if (c == ' ' || c == '0') {
				board.nodes[i][j] = null;
			} else if (c >= '1' && c <= '4') {
				var num = parseInt(c, 10);
				board.nodes[i][j] = new Node(null, 2 * num);
			} else if ('tsdph'.indexOf(c) > -1) {
				board.nodes[i][j] = new Node(c, 2);
			} else if ('TSDPH'.indexOf(c) > -1) {
				board.nodes[i][j] = new Node(c.toLowerCase(), 1);
				board.terminators.push({'x': j, 'y': i});
				terminator_count[c] = (terminator_count[c] || 0) + 1;
			} else {
				board.errors.push('Invalid character: ' + c);
			}
		}
		if (j > board.width){
			board.width = j;
		}
	}
	board.height = i;

	if (board.width < 1 || board.height < 1) {
		board.errors.push('Empty board.');
	}

	if (terminator_count.length === 0) {
		board.errors.push('No terminator node was found.');
	}
	for (var i in terminator_count) {
		if (terminator_count[i] != 2) {
			board.errors.push('There are ' + terminator_count[i] + ' terminators of type ' + i + ', but only 2 are expected.');
		}
	}

	return board;
}

// Receives an already solved board.
// Returns a multi-line string with the solution in ASCII drawing.
function solution_to_text(board) {
	var sol = [];

	// Nodes.
	for (var i = 0; i < board.height; i++) {
		var line1 = [];
		var line2 = [];
		for (var j = 0; j < board.width; j++) {
			var name = ' ';
			var node = board.nodes[i][j];
			if (node) {
				if (node.max_edges === 1) {
					name = node.color.toUpperCase();
				} else {
					name = node.color || '*';
				}
			}
			line1.push(name, ' ');
			line2.push(' ', ' ');
		}
		sol.push(line1, line2);
	}

	// Edges.
	for (var i = 0; i < board.height; i++) {
		for (var j = 0; j < board.width; j++) {
			var node = board.nodes[i][j];
			if (node) {
				for (var k = 0; k < node.edges.length; k++) {
					var edge = node.edges[k];

					var x = j * 2 + edge.direction.dx;
					var y = i * 2 + edge.direction.dy;
					var c = edge.direction.char;
					sol[y][x] = c;
					// Edge color is ignored here.
				}
			}
		}
	}

	var ret = '';
	for (var i = 0; i < sol.length; i++) {
		ret += sol[i].join('') + '\n';
	}
	return ret;
}

//////////////////////////////////////////////////////////////////////
// DOM-related and UI-related manipulation.

function parse_board_from_input() {
	var puzzleinput = document.getElementById('puzzleinput');
	var lines = puzzleinput.value.split(/[\r\n]+/);
	var board = parse_text_input(lines);

	var messages = document.getElementById('messages');
	messages.textContent = board.errors.join('\n');
	messages.classList.remove('busy');

	return board;
}

function build_svg_from_board(board) {
	if (board.width < 1 || board.height < 1) {
		return;
	}

	var svgsolutioncontainer = document.getElementById('svgsolutioncontainer');

	var svg_code = '';

	var width = (board.width * 1.5 - 0.5);
	var height = (board.height * 1.5 - 0.5);
	svg_code += '<svg preserveAspectRatio="xMidYMin" viewBox="0 0 ' + width + ' ' + height + '">';

	var edge_colors = {
		's': '#fc1f20',
		'd': '#0086ff',
		't': '#ffa515',
		'p': '#009e00',
		'h': '#ca197d'
	};

	var revealrange = document.getElementById('revealrange');
	if (board.edge_count === 0) {
		revealrange.disabled = true;
	} else {
		revealrange.disabled = false;

		// Updating the slider to the new edge count.
		var is_reveal_slider_at_max = (revealrange.value === revealrange.max);
		revealrange.max = board.edge_count;
		if (is_reveal_slider_at_max) {
			// If value was already at maximum before, the user likely wants
			// the value at maximum again.
			revealrange.value = revealrange.max;
		}

		// Edge indexes being shuffled in a random order.
		var random_numbers = [];
		for (var i = 0; i < board.edge_count; i++) {
			random_numbers[i] = i;
		}
		shuffle(random_numbers);

		// Building the edges.
		for (var i = 0; i < board.height; i++) {
			for (var j = 0; j < board.width; j++) {
				var node = board.nodes[i][j];
				if (node) {
					for (var k = 0; k < node.edges.length; k++) {
						var edge = node.edges[k];
						svg_code += '<polyline ' +
							'class="edge" '+
							'id="edge' + random_numbers.pop() + '" ' +
							'stroke="' + edge_colors[edge.color] + '" ' +
							'marker-mid="url(#mid_arrow)"' +
							'points="' +
							'' + ((j                        ) * 1.5 + 0.5) + ',' + ((i                        ) * 1.5 + 0.5) + ' ' +
							'' + ((j + edge.direction.dx / 2) * 1.5 + 0.5) + ',' + ((i + edge.direction.dy / 2) * 1.5 + 0.5) + ' ' +
							'' + ((j + edge.direction.dx    ) * 1.5 + 0.5) + ',' + ((i + edge.direction.dy    ) * 1.5 + 0.5) + '" />';
					}
				}
			}
		}
	}

	// Building the nodes.
	for (var i = 0; i < board.height; i++) {
		for (var j = 0; j < board.width; j++) {
			var node = board.nodes[i][j];
			if (node) {
				var name = '';
				if (node.max_edges === 1) {
					name = node.color.toUpperCase();
				} else if (node.color) {
					name = node.color;
				} else {
					name = Math.floor(node.max_edges / 2) + '';
				}

				svg_code += '<use xlink:href="#node_' + name + '" x="' + (j * 1.5) + '" y="' + (i * 1.5) + '" width="1" height="1" />';
			}
		}
	}

	svg_code += '</svg>';
	svgsolutioncontainer.innerHTML = svg_code;

	reveal_edges(revealrange.value);
}

function reveal_edges(how_many) {
	var all_edges = document.querySelectorAll('#svgsolutioncontainer > svg .edge');
	for (var i = 0; i < all_edges.length; i++) {
		all_edges[i].style.display = 'none';
	}
	for (var i = 0; i < how_many; i++) {
		var edge = document.getElementById('edge' + i);
		if (edge) {
			edge.style.display = 'block';
		}
	}
}

//////////////////////////////////////////////////////////////////////
// Web Worker handling.

function interrupt_worker() {
	if (g_worker) {
		g_worker.terminate();
		g_worker = null;

		var solvebutton = document.getElementById('solvebutton');
		solvebutton.value = 'Solve it!';

		var messages = document.getElementById('messages');
		messages.classList.remove('busy');
	}
}

//////////////////////////////////////////////////////////////////////
// Event handling.

function puzzleinput_input_handler() {
	interrupt_worker();
	var board = parse_board_from_input();
	build_svg_from_board(board);
}

function solution_found_handler(e) {
	var solve_finish_date = new Date();
	var solve_time = solve_finish_date.getTime() - g_solve_start_date.getTime();
	solve_time = solve_time / 1000;  // Converting to seconds.

	interrupt_worker();

	var messages = document.getElementById('messages');
	var board = e.data;

	if (board.solution_found === true) {
		messages.textContent = 'Solution found after ' + solve_time.toFixed(1) + 's!';
	} else if (board.solution_found === false) {
		messages.textContent = 'No solution found after ' + solve_time.toFixed(1)+ 's. :(';
	} else {
		console.error('board.solution_found: ' + board.solution_found);
		messages.textContent = 'This should not have happened.';
	}
	messages.classList.remove('busy');

	//console.log(solution_to_text(board));
	build_svg_from_board(board);
}

function solvebutton_click_handler() {
	var messages = document.getElementById('messages');

	if (g_worker) {
		interrupt_worker();
		messages.textContent = 'Interrupted by user.';
	} else {
		var board = parse_board_from_input();

		if (board.errors.length === 0) {
			g_solve_start_date = new Date();

			// Run the solving algorithm in a background thread.
			g_worker = new Worker('algorithm.js');
			g_worker.addEventListener('message', solution_found_handler);
			g_worker.postMessage(board);

			var solvebutton = document.getElementById('solvebutton');
			solvebutton.value = 'Abort!';
			messages.textContent = 'Searching for a solution…';
			messages.classList.add('busy');
		}
	}
}

function revealrange_input_handler() {
	var revealrange = document.getElementById('revealrange');
	reveal_edges(revealrange.value);
}

function showarrowscheckbox_click_handler() {
	var showarrowscheckbox = document.getElementById('showarrowscheckbox');
	var svgsolutioncontainer = document.getElementById('svgsolutioncontainer');

	// Damn IE… Does not support toggle second argument.
	//svgsolutioncontainer.classList.toggle('hidearrows', !showarrowscheckbox.checked);
	if (showarrowscheckbox.checked) {
		svgsolutioncontainer.classList.remove('hidearrows');
	} else {
		svgsolutioncontainer.classList.add('hidearrows');
	}
}

function init() {
	var puzzleinput = document.getElementById('puzzleinput');
	puzzleinput.addEventListener('input', puzzleinput_input_handler);

	var solvebutton = document.getElementById('solvebutton');
	solvebutton.addEventListener('click', solvebutton_click_handler);

	var revealrange = document.getElementById('revealrange');
	revealrange.addEventListener('input', revealrange_input_handler);

	var showarrowscheckbox = document.getElementById('showarrowscheckbox');
	showarrowscheckbox.addEventListener('click', showarrowscheckbox_click_handler);

	puzzleinput_input_handler();
	showarrowscheckbox_click_handler();

	// Preload this file.
	var tmp_worker = new Worker('algorithm.js');
	tmp_worker.terminate();
}

// Global var pointing to the background thread.
var g_worker = null;
// Date object to measure the algorithm time.
var g_solve_start_date = null;

// This script should be included with "defer" attribute.
init();
<|endoftext|>


<commit_before>var noop = function () {};

var SEP = "!",
    END = "~";

var TDC = 'tdc';

// escape characteds used for keys
function escapeKey (key) {
  return String(key).replace(new RegExp(SEP, "g"), "")
                    .replace(new RegExp(END, "g"), "");
}

function trim (str) {
  return str.replace(/^\s+|\s+$/gm,'');
}

function prepKey (prefix, key) {
  return TDC + SEP + prefix + SEP + trim(escapeKey(key)).toLowerCase();
}

module.exports = function (prefix, db) {

  var ret = {};

  ret.save = function (inkey, value, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('put', key, value);
    return db.put(key, value, fn);
  };

  ret.get = function (inkey, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('get', key);
    return db.get(key, fn);
  };

  ret.all = function (query, fn) {
    fn = fn || noop;
    query = query || '';

    var start = prepKey(prefix, query),
        end   = prepKey(prefix, query) + END;

    var users = [];

    console.log('query', start, end);

    db.readStream({ start: start, end: end })
    .on('data', function (entry) {
      var user = entry.value;
      users.push(user);
    })
    .on('close', function () {
      fn(null, users);
    });
  };

  ret.del = function (inkey, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('del', key);
    return db.del(key, fn);
  };

  return ret;
};
<commit_msg>Change db prefix back to bekk from tdc<commit_after>var noop = function () {};

var SEP = "!",
    END = "~";

var DB_PREFIX = 'bekk';

// escape characteds used for keys
function escapeKey (key) {
  return String(key).replace(new RegExp(SEP, "g"), "")
                    .replace(new RegExp(END, "g"), "");
}

function trim (str) {
  return str.replace(/^\s+|\s+$/gm,'');
}

function prepKey (prefix, key) {
  return DB_PREFIX + SEP + prefix + SEP + trim(escapeKey(key)).toLowerCase();
}

module.exports = function (prefix, db) {

  var ret = {};

  ret.save = function (inkey, value, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('put', key, value);
    return db.put(key, value, fn);
  };

  ret.get = function (inkey, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('get', key);
    return db.get(key, fn);
  };

  ret.all = function (query, fn) {
    fn = fn || noop;
    query = query || '';

    var start = prepKey(prefix, query),
        end   = prepKey(prefix, query) + END;

    var users = [];

    console.log('query', start, end);

    db.readStream({ start: start, end: end })
    .on('data', function (entry) {
      var user = entry.value;
      users.push(user);
    })
    .on('close', function () {
      fn(null, users);
    });
  };

  ret.del = function (inkey, fn) {
    fn = fn || noop;
    var key = prepKey(prefix, inkey);
    console.log('del', key);
    return db.del(key, fn);
  };

  return ret;
};
<|endoftext|>


<commit_before>const mapReduce = (arr, fn) => arr.reduce((result, current) => result + fn(current), "");

const generateCreate = (element) => {
  switch (element.type) {
    case "m-fragment":
      return mapReduce(element.children, generateCreate);
      break;
    case "m-expression":
      return `m[${element.index}] = document.createTextNode("");`;
      break;
    case "m-text":
      return `m[${element.index}] = document.createTextNode("${element.content}");`;
      break;
    default:
      return `${mapReduce(element.children, generateCreate)}m[${element.index}] = document.createElement("${element.type}");`;
  }
};

const generateMount = (element, parent) => {
  let generatedMount = "";

  switch (element.type) {
    case "m-fragment":
      const children = element.children;

      for (let i = 0; i < children.length; i++) {
        const child = children[i];
        const childPath = `m[${child.index}]`;

        if (child.type !== "m-text") {
          generatedMount += mapReduce(child.children, (grandchild) => generateMount(grandchild, childPath));
        }

        generatedMount += `${parent}.parentNode.insertBefore(${childPath}, ${parent});`;
      }
      break;
    default:
      const elementPath = `m[${element.index}]`;

      if (element.type !== "m-text" && element.type !== "m-expression") {
        generatedMount += mapReduce(element.children, (child) => generateMount(child, elementPath));
      }

      generatedMount += `${parent}.appendChild(${elementPath});`;
  }

  return generatedMount;
};

const generateUpdate = (element) => {
  switch (element.type) {
    case "m-expression":
      return `m[${element.index}].textContent = ${element.content};`;
      break;
    case "m-text":
      return "";
      break;
    default:
      return mapReduce(element.children, generateUpdate);
  }
};

export const generate = (tree) => {
  return new Function(`return [function () {var m = this.m;${generateCreate(tree)}}, function (root) {var m = this.m;${generateMount(tree, "root")}}, function () {var m = this.m;${tree.dependencies.map((dependency) => `var ${dependency} = this.${dependency};`)}${generateUpdate(tree)}}]`)();
};
<commit_msg>use mapReduce & DOM utilities, correctly mount fragment<commit_after>import { mapReduce } from "../util/util";

const generateCreate = (element) => {
  switch (element.type) {
    case "m-fragment":
      return mapReduce(element.children, generateCreate);
      break;
    case "m-expression":
      return `m[${element.index}] = m.ct("");`;
      break;
    case "m-text":
      return `m[${element.index}] = m.ct("${element.content}");`;
      break;
    default:
      return `${mapReduce(element.children, generateCreate)}m[${element.index}] = m.ce("${element.type}");`;
  }
};

const generateMount = (element, parent) => {
  let generatedMount = "";

  switch (element.type) {
    case "m-fragment":
      return mapReduce(element.children, (child) => generateMount(child, parent));
      break;
    default:
      const elementPath = `m[${element.index}]`;

      if (element.type !== "m-text" && element.type !== "m-expression") {
        generatedMount += mapReduce(element.children, (child) => generateMount(child, elementPath));
      }

      generatedMount += `m.ma(${elementPath}, ${parent});`;
  }

  return generatedMount;
};

const generateUpdate = (element) => {
  switch (element.type) {
    case "m-expression":
      return `m.ut(m[${element.index}], ${element.content});`
      break;
    case "m-text":
      return "";
      break;
    default:
      return mapReduce(element.children, generateUpdate);
  }
};

export const generate = (tree) => {
  return new Function(`return [function () {var m = this.m;${generateCreate(tree)}}, function (root) {var m = this.m;${generateMount(tree, "root")}}, function () {var m = this.m;${tree.dependencies.map((dependency) => `var ${dependency} = this.${dependency};`)}${generateUpdate(tree)}}]`)();
};
<|endoftext|>