<commit_before>'use strict'
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
var Observable = require('vigour-js/lib/observable')
var Base = require('vigour-js/lib/base')
var Property = require('../property')
var _addProperty = Observable.prototype.addNewProperty
var getData = require('../util/getdata')
var merge = require('lodash/object/merge')

var Thunk = function (state) { this.state = state }

// this is nice also for operator element etc -- then we can use different version and dont care
Thunk.prototype.type = 'Thunk'

Thunk.prototype.render = function (previous) {
  var previousState = previous ? previous.state : null
  if ((!previousState || !this.state) || comparestamps(previousState, this.state)) {
    return render(previous, this)
  } else {
    return previous.vnode
  }
}

// make classes for this and just use the element (for now this is fine but not perfect ofc)
// just make widget types
var Element = module.exports = new Observable({
  useVal: true,
  components: {
    property: require('../property').prototype,
    style: require('../property/style'),
    observable: Observable.prototype,
    base: Base.prototype
  },
  properties: {
    widget (obj) {
      this.widget = function (state) {
        this.state = state
      }
      var proto = this.widget.prototype
      proto.update = obj.update
      proto.init = obj.init
      proto.destroy = obj.destroy
      proto.type = 'Widget'
    },
    ChildType: true,
    renderNode: true,
    renderTree: true,
    state: true,
    _lstamp: true,
    _datarender: true,
    _forceUpdates: true,
    _key: true,
    _props: true,
    _force: true,
    node: true,
    type (val, event) {
      if (this.type !== val) {
        this.node = val
        this.type = val // may need this or something...
      }
    },
    DOM (DOMnode) {
      var tree = this.render()
      var rootNode = createElement(tree)
      DOMnode.appendChild(rootNode)
      this.setRenderNode(rootNode, tree)
    }
  },
  _keylists: [ '_props', '_keys' ],
  define: {
    keysCheck (val, key) {
      return val[key] instanceof module.exports
    },
    forceUpdates () {
      console.warn('calling force updates probably spawned from parent subscription -- avoid!', this.path.join('.'))
      var p = this
      while (p && !p._force) {
        p._forceUpdates = true
        p = p.parent
      }
    },
    addNewProperty (key, val) {
      if (val && val._datarender) {
        var p = this
        while (p && !p._datarender) {
          p._datarender = true
          p = p.parent
        }
      }
      return _addProperty.apply(this, arguments)
    },
    setRenderNode (node, tree) {
      this.renderNode = node
      this.renderTree = tree
    },
    compare: comparestamps, // this is a little bit strange now since we dont use the ref
    apply (state) {
      this.applyContext(state.context)
      this.state = state
      return this
    },
    render (data, state, event, prev) {
      if (this.__input === null) {
        return
      }

      if (this._forceUpdates) {
        this.forceUpdates()
      }

      data = getData(this, data)
      var dstamp = this._datarender && data && data._lstamp
      var force = this._force || !dstamp && this._datarender || this._forceUpdates
      if (this.$ && ((data && data.__input === null || !data))) {
        return
      }

      var lstamp = this._lstamp
      var stamp = (dstamp && (lstamp ? dstamp + lstamp : dstamp)) || lstamp

      state = state || {
        force: force,
        stamp: stamp,
        data: data,
        context: this.storeContext(), // this is going to be smarter first check then maybe reuse
        elem: this,
        elemid: this.__input !== null && this.uid,
        dataid: this._datarender && data && data.uid // maybe need null
      }

      if (prev && prev.next) {
        merge(state, prev.next)
      }

      if (this.widget) {
        return new this.widget(state) //eslint-disable-line
      } else {
        return new Thunk(state)
      }
    }
  },
  inject: [
    require('./map'),
    require('./patch'),
    require('vigour-js/lib/base/context/key'),
    require('../util/validnode')
  ],
  Child: 'Constructor'
}).Constructor

// maybe allways do this
Element.prototype.ChildType = Element
Element.Thunk = Thunk
Element.isProp = isProp
Element.addChild = addChild
Element.loopProperty = loopProperty

function comparestamps (previousState, currentState) {
  var res =
    currentState.force ||
    previousState.stamp !== currentState.stamp ||
    currentState.elemid !== previousState.elemid ||
    currentState.dataid !== previousState.dataid
  if (!res && !currentState.props) {
    currentState.props = previousState.props
  }
  return res
}

function render (previousThunk, currentThunk) {
  return genericRender.call(
    currentThunk.state.elem,
    currentThunk.state.data,
    currentThunk,
    previousThunk
  )
}

// reuse this
function genericRender (data, current, prev) {
  this.apply(current.state)
  var children = []
  var props = current.state && current.state.props && current.state.props.properties || {}

  if (this.keys('_props', isProp)) {
    for (let i = 0, len = this._props.length; i < len; i++) {
      let prop = this._props[i]
      loopProperty(this[prop], data, props, children, current, prev)
    }
  }

  if (this.$collection) {
    if (data && data.__input !== null) {
      if (this.keys()) {
        for (let i = 0, len = this._keys.length; i < len; i++) {
          if (data[this._keys[i]] === void 0) {
            let ret = this[this._keys[i]].render(data, void 0, void 0, prev)
            if (ret) { children.push(ret) }
          }
        }
      }
      if (data.keys()) {
        for (let i = 0, len = data._keys.length; i < len; i++) {
          let key = data._keys[i]
          if (!this._properties[key] || (this._properties[key] instanceof Element)) {
            addChild.call(this, data[key], key, children)
          }
          addChild.call(this, data[key], key, children)
        }
      }
    }
  } else {
    if (this.keys()) {
      for (let i = 0, len = this._keys.length; i < len; i++) {
        let ret = this[this._keys[i]].render(data, void 0, void 0, prev)
        if (ret) { children.push(ret) }
      }
    }
  }

  if (!props.className) {
    var prepped = (this.key || '') + ((this.type && this.type !== this._node) ? ' type-' + this.type : '')
    if (prepped) {
      props.className = prepped
    }
  }

  return h(this.node, props, children)
}

function isProp (val, key) {
  return val[key] instanceof Property
}

function loopProperty (property, data, props, children, current, prev) {
  if (property.render) {
    let parsed = getData(property, data)
    if (property.compare(property, parsed, props, children, current, prev)) {
      return
    }
    if (parsed instanceof Observable) {
      parsed = property.parseValue(parsed.val) // this and getdata will all be replaced!
    } else {
      if (parsed !== void 0) {
        parsed = property.parseValue(parsed || data && data.val)
      } else {
        parsed = property.parseValue(data && data.val)
      }
    }
    if (parsed !== void 0) {
      property.render(parsed, props, children, data, current, prev)
    }
    if (property.keys()) {
      for (var i = 0, len = property._keys.length; i < len; i++) {
        loopProperty(property[property._keys[i]], data, props, children, current, prev)
      }
    }
  }
}

function addChild (property, key, children) {
  var type = key
  var ret
  if (this[key] === null) {
    console.warn('removed an element (and resolved context) in a collection are you sure?')
  } else if (this[key] && this[key] instanceof Element) {
    ret = this[key].render(property)
    if (ret) { children.push(ret) }
  } else if (
    this.properties[key] ||
    (
      (type = this.mapProperty(key, property)) &&
      this.properties[type]
    )
  ) {
    if (this.properties[type].base && this.properties[type].base.render) {
      this.properties[type].base._context = this
      this.properties[type].base._contextLevel = 1
      this.properties[type].base._contextKey = key

      ret = this.properties[type].base.render(property)
      if (ret) { children.push(ret) }
    }
  } else if (this.ChildConstructor && this.ChildConstructor !== module.exports) { // speed this up slow check!
    this.Child.prototype._context = this
    this.Child.prototype._contextLevel = 1
    this.Child.prototype._contextKey = key
    ret = this.Child.prototype.render(property)
    if (ret) { children.push(ret) }
  }
  return ret
}
<commit_msg>added getChild<commit_after>'use strict'
var h = require('virtual-dom/h')
var createElement = require('virtual-dom/create-element')
var Observable = require('vigour-js/lib/observable')
var Base = require('vigour-js/lib/base')
var Property = require('../property')
var _addProperty = Observable.prototype.addNewProperty
var getData = require('../util/getdata')
var merge = require('lodash/object/merge')

var Thunk = function (state) { this.state = state }

// this is nice also for operator element etc -- then we can use different version and dont care
Thunk.prototype.type = 'Thunk'

Thunk.prototype.render = function (previous) {
  var previousState = previous ? previous.state : null
  if ((!previousState || !this.state) || comparestamps(previousState, this.state)) {
    return render(previous, this)
  } else {
    return previous.vnode
  }
}

// make classes for this and just use the element (for now this is fine but not perfect ofc)
// just make widget types
var Element = module.exports = new Observable({
  useVal: true,
  components: {
    property: require('../property').prototype,
    style: require('../property/style'),
    observable: Observable.prototype,
    base: Base.prototype
  },
  properties: {
    widget (obj) {
      this.widget = function (state) {
        this.state = state
      }
      var proto = this.widget.prototype
      proto.update = obj.update
      proto.init = obj.init
      proto.destroy = obj.destroy
      proto.type = 'Widget'
    },
    ChildType: true,
    renderNode: true,
    renderTree: true,
    state: true,
    _lstamp: true,
    _datarender: true,
    _forceUpdates: true,
    _key: true,
    _props: true,
    _force: true,
    node: true,
    type (val, event) {
      if (this.type !== val) {
        this.node = val
        this.type = val // may need this or something...
      }
    },
    DOM (DOMnode) {
      var tree = this.render()
      var rootNode = createElement(tree)
      DOMnode.appendChild(rootNode)
      this.setRenderNode(rootNode, tree)
    }
  },
  _keylists: [ '_props', '_keys' ],
  define: {
    keysCheck (val, key) {
      return val[key] instanceof module.exports
    },
    forceUpdates () {
      console.warn('calling force updates probably spawned from parent subscription -- avoid!', this.path.join('.'))
      var p = this
      while (p && !p._force) {
        p._forceUpdates = true
        p = p.parent
      }
    },
    addNewProperty (key, val) {
      if (val && val._datarender) {
        var p = this
        while (p && !p._datarender) {
          p._datarender = true
          p = p.parent
        }
      }
      return _addProperty.apply(this, arguments)
    },
    setRenderNode (node, tree) {
      this.renderNode = node
      this.renderTree = tree
    },
    compare: comparestamps, // this is a little bit strange now since we dont use the ref
    apply (state) {
      this.applyContext(state.context)
      this.state = state
      return this
    },
    render (data, state, event, prev) {
      if (this.__input === null) {
        return
      }

      if (this._forceUpdates) {
        this.forceUpdates()
      }

      data = getData(this, data)
      var dstamp = this._datarender && data && data._lstamp
      var force = this._force || !dstamp && this._datarender || this._forceUpdates
      if (this.$ && ((data && data.__input === null || !data))) {
        return
      }

      var lstamp = this._lstamp
      var stamp = (dstamp && (lstamp ? dstamp + lstamp : dstamp)) || lstamp

      state = state || {
        force: force,
        stamp: stamp,
        data: data,
        context: this.storeContext(), // this is going to be smarter first check then maybe reuse
        elem: this,
        elemid: this.__input !== null && this.uid,
        dataid: this._datarender && data && data.uid // maybe need null
      }

      if (prev && prev.next) {
        merge(state, prev.next)
      }

      if (this.widget) {
        return new this.widget(state) //eslint-disable-line
      } else {
        return new Thunk(state)
      }
    }
  },
  inject: [
    require('./map'),
    require('./patch'),
    require('vigour-js/lib/base/context/key'),
    require('../util/validnode')
  ],
  Child: 'Constructor'
}).Constructor

// maybe allways do this
Element.prototype.ChildType = Element
Element.Thunk = Thunk
Element.isProp = isProp
Element.addChild = addChild
Element.loopProperty = loopProperty

function comparestamps (previousState, currentState) {
  var res =
    currentState.force ||
    previousState.stamp !== currentState.stamp ||
    currentState.elemid !== previousState.elemid ||
    currentState.dataid !== previousState.dataid
  if (!res && !currentState.props) {
    currentState.props = previousState.props
  }
  return res
}

function render (previousThunk, currentThunk) {
  return genericRender.call(
    currentThunk.state.elem,
    currentThunk.state.data,
    currentThunk,
    previousThunk
  )
}

// reuse this
function genericRender (data, current, prev) {
  this.apply(current.state)
  var children = []
  var props = current.state && current.state.props && current.state.props.properties || {}

  if (this.keys('_props', isProp)) {
    for (let i = 0, len = this._props.length; i < len; i++) {
      let prop = this._props[i]
      loopProperty(this[prop], data, props, children, current, prev)
    }
  }

  if (this.$collection) {
    if (data && data.__input !== null) {
      if (this.keys()) {
        for (let i = 0, len = this._keys.length; i < len; i++) {
          if (data[this._keys[i]] === void 0) {
            let ret = this[this._keys[i]].render(data, void 0, void 0, prev)
            if (ret) { children.push(ret) }
          }
        }
      }
      if (data.keys()) {
        for (let i = 0, len = data._keys.length; i < len; i++) {
          let key = data._keys[i]
          if (!this._properties[key] || (this._properties[key] instanceof Element)) {
            addChild.call(this, data[key], key, children)
          }
        }
      }
    }
  } else {
    if (this.keys()) {
      for (let i = 0, len = this._keys.length; i < len; i++) {
        let ret = this[this._keys[i]].render(data, void 0, void 0, prev)
        if (ret) { children.push(ret) }
      }
    }
  }

  if (!props.className) {
    var prepped = (this.key || '') + ((this.type && this.type !== this._node) ? ' type-' + this.type : '')
    if (prepped) {
      props.className = prepped
    }
  }

  return h(this.node, props, children)
}

function isProp (val, key) {
  return val[key] instanceof Property
}

function loopProperty (property, data, props, children, current, prev) {
  if (property.render) {
    let parsed = getData(property, data)
    if (property.compare(property, parsed, props, children, current, prev)) {
      return
    }
    if (parsed instanceof Observable) {
      parsed = property.parseValue(parsed.val) // this and getdata will all be replaced!
    } else {
      if (parsed !== void 0) {
        parsed = property.parseValue(parsed || data && data.val)
      } else {
        parsed = property.parseValue(data && data.val)
      }
    }
    if (parsed !== void 0) {
      property.render(parsed, props, children, data, current, prev)
    }
    if (property.keys()) {
      for (var i = 0, len = property._keys.length; i < len; i++) {
        loopProperty(property[property._keys[i]], data, props, children, current, prev)
      }
    }
  }
}

function addChild (property, key, children) {
  var type = key
  var ret
  if (this[key] === null) {
    console.warn('removed an element (and resolved context) in a collection are you sure?')
  } else if (this[key] && this[key] instanceof Element) {
    ret = this[key].render(property)
    if (ret) { children.push(ret) }
  } else if (
    this.properties[key] ||
    (
      (type = this.mapProperty(key, property)) &&
      this.properties[type]
    )
  ) {
    if (this.properties[type].base && this.properties[type].base.render) {
      this.properties[type].base._context = this
      this.properties[type].base._contextLevel = 1
      this.properties[type].base._contextKey = key

      ret = this.properties[type].base.render(property)
      if (ret) { children.push(ret) }
    }
  } else if (this.ChildConstructor && this.ChildConstructor !== module.exports) { // speed this up slow check!
    this.Child.prototype._context = this
    this.Child.prototype._contextLevel = 1
    this.Child.prototype._contextKey = key
    ret = this.Child.prototype.render(property)
    if (ret) { children.push(ret) }
  }
  return ret
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*global $:false */

'use strict';

$(document).ready(function() {

  // Only works on Chrome
  if (!$('body').hasClass('chrome')) {
    $('.unsupported-overlay').show();
  }

  // UI
  var micButton = $('.micButton'),
  micText = $('.micText'),
  transcript = $('#text'),
  errorMsg = $('.errorMsg');

  function displayError(error) {
    var message = error;
    try {
      var errorJson = JSON.parse(error);
      message = JSON.stringify(errorJson, null, 2);
    } catch (e) {
      message = error;
    }

    errorMsg.text(message);
    errorMsg.show();
    transcript.hide();
  }

  //Sample audios
  var audio1 = 'audio/sample1.wav',
      audio2 = 'audio/sample2.wav';

  function _error(xhr) {
    $('.loading').hide();
    displayError('Error processing the request, please try again.');
  }

  function stopSounds() {
    $('.sample2').get(0).pause();
    $('.sample2').get(0).currentTime = 0;
    $('.sample1').get(0).pause();
    $('.sample1').get(0).currentTime = 0;
  }

  $('.audio1').click(function() {
    $('.audio-staged audio').attr('src', audio1);
    stopSounds();
    $('.sample1').get(0).play();
  });

  $('.audio2').click(function() {
    $('.audio-staged audio').attr('src', audio2);
    stopSounds();
    $('.sample2').get(0).play();
  });

  $('.send-api-audio1').click(function() {
    transcriptAudio(audio1);
  });

  $('.send-api-audio2').click(function() {
    transcriptAudio(audio2);
  });

  function showAudioResult(data){
    $('.loading').hide();
    transcript.empty();
    $('

').appendTo(transcript);
    showResult(data);
  }
  // submit event
  function transcriptAudio(audio) {
    $('.loading').show();
    $('.error').hide();
    transcript.hide();
    $('.url-input').val(audio);
    $('.upload-form').hide();
    // Grab all form data
    $.ajax({
      url: '/',
      type: 'POST',
      data: $('.upload-form').serialize(),
      success: showAudioResult,
      error: _error
    });
  }

  function sendDraggedFile(file) {
    $('.loading').show();
    console.log('loading blob: ');
    // ws.send(file);
    // ws.send(JSON.stringify({'action': 'stop'}));
  }

  function handleFileUploadEvent(evt) {
    console.log('uploading file');
    var file = evt.dataTransfer.files[0];
    var objectUrl = URL.createObjectURL(file);
    sendDraggedFile(file);
    $('.custom.sample-title').text(file.name);
    $('.audio3').click(function() {
      console.log('evt', evt);
      $('.sample3').prop('src', objectUrl);
      stopSounds();
      $('.sample3').get(0).play();
    });
    $('.send-api-audio3').click(function() {
      console.log('click! API');
      sendDraggedFile(file);
    });
  }

  var target = $("#fileUploadTarget");
  target.on('dragenter', function (e) {
    e.stopPropagation();
    e.preventDefault();
    $(this).css('border', '2px solid #0B85A1');
  });

  target.on('dragover', function (e) {
    e.stopPropagation();
    e.preventDefault();
  });

  target.on('drop', function (e) {

    $(this).css('border', '2px dotted #0B85A1');
    e.preventDefault();
    var evt = e.originalEvent;

    // Handle dragged file event
    handleFileUploadEvent(evt);
  });

  console.log('mic', Microphone);

  // ncaught RangeError: Offset is outside the bounds of the DataView

  var options = {
    samplingRate: 16000
  };

  var mic = new Microphone();

  function initSocket(socket) {

    var running = false;

    var time = performance.now || performance.webkitNow,
        t0, t1;

    var session = {
      audio: true,
      video: false
    };

    var recordButton = document.getElementById("recordButton");

    recordButton.onclick = function(evt) {
      if (running) {
        console.log('stopping mic');
        mic.stop();
        running = false;
      } else {
        console.log('starting mic');
        mic.record();
        running = true;
      }
    };

    mic.onAudio = function(blob) {

      setTimeout(function() {
        socket.send(blob);
      }, 100);

    };

    function onError(err) {
      console.log('audio error: ', err);
    }

  }

  function websocketTest(token) {
    // Test out websocket
    // var wsUrl = 'wss://stream-d.watsonplatform.net/speech-to-text-beta/api/v1/recognize?watson-token=' + token;
    var wsUrl = 'ws://127.0.0.1:8020/speech-to-text-beta/api/v1/recognize';
    var ws = new WebSocket(wsUrl);
    var $textArea = $('#resultsText');
    ws.onopen = function(evt) {
      console.log('ws opened');
      ws.send(JSON.stringify({
        'action': 'start',
        'content-type': 'audio/l16;rate=16000',
        'interim_results': true,
        'continuous': true
      }));
      initSocket(ws);
    };
    ws.onmessage = function(evt) {
      console.log('ws message', evt.data);
      var msg = evt.data;
      if (msg.results) {
        showResult(msg);
        var transcript = msg.results[0].alternatives[0].transcript;
        console.log('transcript', transcript);
        $('#resultsText').val(transcript);
      }
    };
    ws.onerror = function(evt) {
      console.log('ws error', evt);
    };
    return ws;
  }

  function callRESTApi(token) {
    // var modelUrl = 'https://stream-d.watsonplatform.net/speech-to-text-beta/api/v1/models';
    var modelUrl = '/models';
    var sttRequest = new XMLHttpRequest();
    sttRequest.open("GET", modelUrl, true);
    sttRequest.withCredentials = true;
    sttRequest.setRequestHeader('Accept', 'application/json');
    sttRequest.setRequestHeader('X-Watson-Authorization-Token', token);
    sttRequest.onload = function(evt) {
      console.log('STT Models ', sttRequest.responseText);
      // We wait until we've given this request a chance to load and (ideally) set the cookie
      // But we get a net::ERR_CONNECTION_REFUSED, apparantly because no cookie is set
      // websocketTest(sttRequest.responseText);
      console.log('models', sttRequest.responseText);
    };
    sttRequest.send();
  }
  callRESTApi('');
  // // callRESTApi(TOKEN);
  // // Make call to API to try and get cookie
  // var url = '/token';
  // var tokenRequest = new XMLHttpRequest();
  // tokenRequest.open("GET", url, true);
  // tokenRequest.onload = function(evt) {
  //   var token = tokenRequest.responseText;
  //   console.log('Token ', decodeURIComponent(token));
  //
  //   callRESTApi(token);
  // }
  //
  // tokenRequest.send();
  var arr = [{
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "blah interim "
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "int ...yes three s. "
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "yes the one two three s. "
              }
           ],
           "final": true
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "another interim ..."
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "last one transcript. "
              }
           ],
           "final": true
        }
     ],
     "result_index": 0
  }];

  var baseString = '';

  function showResult(data) {
    //if there are transcripts
    if (data.results && data.results.length > 0) {

      var text = data.results[0].alternatives[0].transcript || '';

      //if is a partial transcripts
      if (data.results.length === 1 ) {

        //Capitalize first word
        // if final results, append a new paragraph
        if (data.results[0].final){
          console.log('final res:', text);
          baseString += text;
          baseString = baseString.charAt(0).toUpperCase() + baseString.substring(1);
          baseString = baseString.trim() + '.';
          $('#resultsText').val(baseString);
        } else {
          console.log('interimResult res:', text);
          var temp = baseString + text;
          $('#resultsText').val(temp);
        }
      }
    }
    // transcript.show();
  }

  arr.forEach(function(sample, i) {
    console.log('next result');
    setTimeout(function() {
      if (sample.results) {
        showResult(sample);
      }
    }, i * 1000);
  });

  // websocketTest()

});

<commit_msg>Checkpoint commit: adding additional DOM features to client-side demo<commit_after>/**
 * Copyright 2014 IBM Corp. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*global $:false */

'use strict';

$(document).ready(function() {

  // Only works on Chrome
  if (!$('body').hasClass('chrome')) {
    $('.unsupported-overlay').show();
  }

  // UI
  var micButton = $('.micButton'),
  micText = $('.micText'),
  transcript = $('#text'),
  errorMsg = $('.errorMsg');

  function displayError(error) {
    var message = error;
    try {
      var errorJson = JSON.parse(error);
      message = JSON.stringify(errorJson, null, 2);
    } catch (e) {
      message = error;
    }

    errorMsg.text(message);
    errorMsg.show();
    transcript.hide();
  }

  //Sample audios
  var audio1 = 'audio/sample1.wav',
      audio2 = 'audio/sample2.wav';

  function _error(xhr) {
    $('.loading').hide();
    displayError('Error processing the request, please try again.');
  }

  function stopSounds() {
    $('.sample2').get(0).pause();
    $('.sample2').get(0).currentTime = 0;
    $('.sample1').get(0).pause();
    $('.sample1').get(0).currentTime = 0;
  }

  $('.audio1').click(function() {
    $('.audio-staged audio').attr('src', audio1);
    stopSounds();
    $('.sample1').get(0).play();
  });

  $('.audio2').click(function() {
    $('.audio-staged audio').attr('src', audio2);
    stopSounds();
    $('.sample2').get(0).play();
  });

  $('.send-api-audio1').click(function() {
    transcriptAudio(audio1);
  });

  $('.send-api-audio2').click(function() {
    transcriptAudio(audio2);
  });

  function showAudioResult(data){
    $('.loading').hide();
    transcript.empty();
    $('

').appendTo(transcript);
    showResult(data);
  }

  function initFileUpload(socket) {
    function sendDraggedFile(file) {
      $('.loading').show();
      console.log('loading blob: ');
      ws.send(file);
      ws.send(JSON.stringify({'action': 'stop'}));
    }

    function handleFileUploadEvent(evt) {
      console.log('uploading file');
      var file = evt.dataTransfer.files[0];
      var objectUrl = URL.createObjectURL(file);
      sendDraggedFile(file);
      $('.custom.sample-title').text(file.name);
      $('.audio3').click(function() {
        console.log('evt', evt);
        $('.sample3').prop('src', objectUrl);
        stopSounds();
        $('.sample3').get(0).play();
      });
      $('.send-api-audio3').click(function() {
        console.log('click! API');
        sendDraggedFile(file);
      });
    }

    var target = $("#fileUploadTarget");
    target.on('dragenter', function (e) {
      e.stopPropagation();
      e.preventDefault();
      $(this).css('border', '2px solid #0B85A1');
    });

    target.on('dragover', function (e) {
      e.stopPropagation();
      e.preventDefault();
    });

    target.on('drop', function (e) {

      $(this).css('border', '2px dotted #0B85A1');
      e.preventDefault();
      var evt = e.originalEvent;

      // Handle dragged file event
      handleFileUploadEvent(evt);
    });
  }

  // ncaught RangeError: Offset is outside the bounds of the DataView

  function showResult(data) {
    //if there are transcripts
    if (data.results && data.results.length > 0) {

      var text = data.results[0].alternatives[0].transcript || '';

      //if is a partial transcripts
      if (data.results.length === 1 ) {

        //Capitalize first word
        // if final results, append a new paragraph
        if (data.results[0].final){
          console.log('final res:', text);
          baseString += text;
          baseString = baseString.charAt(0).toUpperCase() + baseString.substring(1);
          baseString = baseString.trim() + '.';
          $('#resultsText').val(baseString);
        } else {
          console.log('interimResult res:', text);
          var temp = baseString + text;
          $('#resultsText').val(temp);
        }
      }
    }
  }

  function initSpeech(socket) {

    var mic = new Microphone();

    var running = false;
    var recordButton = document.getElementById("recordButton");
    recordButton.onclick = function(evt) {
      if (running) {
        console.log('stopping mic');
        mic.stop();
        running = false;
      } else {
        console.log('starting mic');
        mic.record();
        running = true;
      }
    };
    var count = 0;
    mic.onAudio = function(blob) {
      // setTimeout(function() {
        socket.send(blob)
      // }, count * 100);
      // count++;
    };

    function onError(err) {
      console.log('audio error: ', err);
    }

  }

  function websocketTest(token) {
    // Test out websocket
    var wsUrl = 'wss://stream-d.watsonplatform.net/speech-to-text-beta/api/v1/recognize?watson-token=' + token;
    var ws = new WebSocket(wsUrl);
    var $textArea = $('#resultsText');
    ws.onopen = function(evt) {
      console.log('ws opened');
      ws.send(JSON.stringify({
        'action': 'start',
        'content-type': 'audio/l16;rate=16000',
        'interim_results': true,
        'continuous': true
        'word_confidence': true,
        'timestamps': true,
        'max_alternatives': 3
      }));
      initSpeech(ws);
    };
    ws.onmessage = function(evt) {
      console.log('ws message', evt.data);
      var msg = JSON.parse(evt.data);
      if (msg.results) {
        showResult(msg);
        console.log('result', msg);
      }
    };
    ws.onerror = function(evt) {
      console.log('ws error', evt);
    };
    return ws;
  }

  function callRESTApi(token) {
    var modelUrl = 'https://stream-d.watsonplatform.net/speech-to-text-beta/api/v1/models';
    var sttRequest = new XMLHttpRequest();
    sttRequest.open("GET", modelUrl, true);
    sttRequest.withCredentials = true;
    sttRequest.setRequestHeader('Accept', 'application/json');
    sttRequest.setRequestHeader('X-Watson-Authorization-Token', token);
    sttRequest.onload = function(evt) {
      console.log('STT Models ', sttRequest.responseText);
      // We wait until we've given this request a chance to load and (ideally) set the cookie
      // But we get a net::ERR_CONNECTION_REFUSED, apparantly because no cookie is set
      // websocketTest(sttRequest.responseText);
      console.log('models', sttRequest.responseText);
      // var models = JSON.parse(sttRequest.responseText);
    };
    sttRequest.send();
  }
  // callRESTApi(TOKEN);
  // Make call to API to try and get cookie
  var url = '/token';
  var tokenRequest = new XMLHttpRequest();
  tokenRequest.open("GET", url, true);
  tokenRequest.onload = function(evt) {
    var token = tokenRequest.responseText;
    console.log('Token ', decodeURIComponent(token));

    // callRESTApi(token);
    websocketTest(token);

  }

  tokenRequest.send();
  var arr = [{
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "blah interim "
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "int ...yes three s. "
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "yes the one two three s. "
              }
           ],
           "final": true
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "another interim ..."
              }
           ],
           "final": false
        }
     ],
     "result_index": 0
  }, {
     "results": [
        {
           "alternatives": [
              {
                 "confidence": 0.7147521376609802,
                 "transcript": "last one transcript. "
              }
           ],
           "final": true
        }
     ],
     "result_index": 0
  }];

  var baseString = '';

  // arr.forEach(function(sample, i) {
  //   console.log('next result');
  //   setTimeout(function() {
  //     if (sample.results) {
  //       showResult(sample);
  //     }
  //   }, i * 1000);
  // });

});

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
 *
 * zfs.js: Endpoints to manage ZFS datasets and pools
 */

var common = require('../common');
var restify = require('restify');
var util = require('util');
var ModelServer = require('../models/server');

function ZFS() {}

ZFS.listDatasets = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_datasets', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list datasets:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

ZFS.createDataset = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_create_dataset', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot create dataset:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.createSnapshot = function (req, res, next) {
    var server = req.params.server;

    var name = req.params.name;
    var snapshot = req.params.dataset + '@' + name;

    server.zfsTask(
        'zfs_snapshot_dataset',
        { dataset: snapshot },
        function (err) {
            if (err) {
                next(new restify.InternalError(
                    'cannot create snapshot: ' + err.message));
                return;
            }
            res.send(204);
            next();
            return;
        });
};

ZFS.rollbackSnapshot = function (req, res, next) {
    var server = req.params.server;

    var name = req.params.name;
    var snapshot = req.params.dataset + '@' + name;

    server.zfsTask(
        'zfs_rollback_dataset',
        { dataset: snapshot },
        function (err) {
            if (err) {
                next(new restify.InternalError(
                    'cannot create snapshot: ' + err.message));
                return;
            }
            res.send(204);
            next();
            return;
        });
};

ZFS.listSnapshots = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_snapshots', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list snapshots:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

function findProps(params) {
    var properties = [];

    for (var key in params) {
        if (params.hasOwnProperty(key) &&
            key.substr(0, 4) === 'prop') {
            properties.push(params[key]);
        }
    }

    return (properties);
}

ZFS.getAllProperties = function (req, res, next) {
    var server = req.params.server;

    var options = {};
    var properties = findProps(req.params);
    if (properties.length > 0)
        options.properties = properties;

    server.zfsTask('zfs_get_properties', options, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot get properties:' + err.message)));
        }

        // XXX I need to talk to Orlando about this
        delete results.log;

        res.send(results);
        return (next());
    });
};

ZFS.getProperties = function (req, res, next) {
    var server = req.params.server;
    var dataset = req.params.dataset;

    var options = {};
    options.dataset = dataset;
    var properties = findProps(req.params);
    if (properties.length > 0)
        options.properties = properties;

    // XXX Handle case where pool is specified or not

    server.zfsTask('zfs_get_properties', options, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot get properties:' + err.message)));
        }

        // XXX I need to talk to Orlando about this
        delete results.log;

        res.send(results);
        return (next());
    });
};

ZFS.setProperties = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_set_properties', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot set properties:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.destroyDataset = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_destroy_dataset', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot destroy dataset:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.listZpools = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_pools', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list pools:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

function attachTo(http) {
    var before = [
        function (req, res, next) {
            if (!req.params.server_uuid) {
                next();
                return;
            }

            req.params.server = new ModelServer(req.params.server_uuid);
            req.params.server.get(function (error, server) {
                // Check if any servers were returned
                if (!server) {
                    var errorMsg
                        = 'Server ' + req.params.server_uuid + ' not found';
                    next(
                        new restify.ResourceNotFoundError(errorMsg));
                    return;
                }
                req.params.serverAttributes = server;
                next();
            });
        }
    ];

    // List ZFS datasets on a server
    http.get(
        { path: '/servers/:server_uuid/datasets', name: 'ListDatasets' },
        before, ZFS.listDatasets);

    // Create ZFS dataset
    http.post(
        { path: '/servers/:server_uuid/datasets', name: 'CreateDataset' },
        before, ZFS.createDataset);

    // Create a snapshot
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/snapshot',
          name: 'CreateSnapshot' },
        before, ZFS.createSnapshot);

    // Rollback a snapshot
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/rollback',
          name: 'RollbackSnapshot' },
        before, ZFS.rollbackSnapshot);

    // List snapshots
    http.get(
        { path: '/servers/:server_uuid/datasets/:dataset/snapshots',
          name: 'ListSnapshots' },
        before, ZFS.listSnapshot);

    // Get ZFS properties for all dataset
    http.get(
        { path: '/servers/:server_uuid/dataset-properties',
          name: 'GetAllProperties' },
        before, ZFS.getAllProperties);

    // Get ZFS properties for a dataset
    http.get(
        { path: '/servers/:server_uuid/datasets/:dataset/properties',
          name: 'GetProperties' },
        before, ZFS.getProperties);

    // Set ZFS properties for a dataset
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/properties',
          name: 'SetProperties' },
        before, ZFS.setProperties);

    // Destroy ZFS dataset
    http.del(
        { path: '/servers/:server_uuid/datasets/:dataset',
          name: 'DestroyDataset' },
        before, ZFS.destroyDataset);

    // List ZFS pools on a server
    http.get(
        { path: '/servers/:server_uuid/zpools', name: 'ListZpools' },
        before, ZFS.listZpools);
}

exports.attachTo = attachTo;
<commit_msg>CNAPI-118: Fix a typo in endpoint name<commit_after>/*
 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
 *
 * zfs.js: Endpoints to manage ZFS datasets and pools
 */

var common = require('../common');
var restify = require('restify');
var util = require('util');
var ModelServer = require('../models/server');

function ZFS() {}

ZFS.listDatasets = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_datasets', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list datasets:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

ZFS.createDataset = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_create_dataset', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot create dataset:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.createSnapshot = function (req, res, next) {
    var server = req.params.server;

    var name = req.params.name;
    var snapshot = req.params.dataset + '@' + name;

    server.zfsTask(
        'zfs_snapshot_dataset',
        { dataset: snapshot },
        function (err) {
            if (err) {
                next(new restify.InternalError(
                    'cannot create snapshot: ' + err.message));
                return;
            }
            res.send(204);
            next();
            return;
        });
};

ZFS.rollbackSnapshot = function (req, res, next) {
    var server = req.params.server;

    var name = req.params.name;
    var snapshot = req.params.dataset + '@' + name;

    server.zfsTask(
        'zfs_rollback_dataset',
        { dataset: snapshot },
        function (err) {
            if (err) {
                next(new restify.InternalError(
                    'cannot create snapshot: ' + err.message));
                return;
            }
            res.send(204);
            next();
            return;
        });
};

ZFS.listSnapshots = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_snapshots', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list snapshots:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

function findProps(params) {
    var properties = [];

    for (var key in params) {
        if (params.hasOwnProperty(key) &&
            key.substr(0, 4) === 'prop') {
            properties.push(params[key]);
        }
    }

    return (properties);
}

ZFS.getAllProperties = function (req, res, next) {
    var server = req.params.server;

    var options = {};
    var properties = findProps(req.params);
    if (properties.length > 0)
        options.properties = properties;

    server.zfsTask('zfs_get_properties', options, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot get properties:' + err.message)));
        }

        // XXX I need to talk to Orlando about this
        delete results.log;

        res.send(results);
        return (next());
    });
};

ZFS.getProperties = function (req, res, next) {
    var server = req.params.server;
    var dataset = req.params.dataset;

    var options = {};
    options.dataset = dataset;
    var properties = findProps(req.params);
    if (properties.length > 0)
        options.properties = properties;

    // XXX Handle case where pool is specified or not

    server.zfsTask('zfs_get_properties', options, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot get properties:' + err.message)));
        }

        // XXX I need to talk to Orlando about this
        delete results.log;

        res.send(results);
        return (next());
    });
};

ZFS.setProperties = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_set_properties', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot set properties:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.destroyDataset = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_destroy_dataset', req.params, function (err) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot destroy dataset:' + err.message)));
        }

        res.send(204);
        return (next());
    });
};

ZFS.listZpools = function (req, res, next) {
    var server = req.params.server;

    server.zfsTask('zfs_list_pools', req.params, function (err, results) {
        if (err) {
            return (next(new restify.InternalError(
                'cannot list pools:' + err.message)));
        }

        res.send(results);
        return (next());
    });
};

function attachTo(http) {
    var before = [
        function (req, res, next) {
            if (!req.params.server_uuid) {
                next();
                return;
            }

            req.params.server = new ModelServer(req.params.server_uuid);
            req.params.server.get(function (error, server) {
                // Check if any servers were returned
                if (!server) {
                    var errorMsg
                        = 'Server ' + req.params.server_uuid + ' not found';
                    next(
                        new restify.ResourceNotFoundError(errorMsg));
                    return;
                }
                req.params.serverAttributes = server;
                next();
            });
        }
    ];

    // List ZFS datasets on a server
    http.get(
        { path: '/servers/:server_uuid/datasets', name: 'ListDatasets' },
        before, ZFS.listDatasets);

    // Create ZFS dataset
    http.post(
        { path: '/servers/:server_uuid/datasets', name: 'CreateDataset' },
        before, ZFS.createDataset);

    // Create a snapshot
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/snapshot',
          name: 'CreateSnapshot' },
        before, ZFS.createSnapshot);

    // Rollback a snapshot
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/rollback',
          name: 'RollbackSnapshot' },
        before, ZFS.rollbackSnapshot);

    // List snapshots
    http.get(
        { path: '/servers/:server_uuid/datasets/:dataset/snapshots',
          name: 'ListSnapshots' },
        before, ZFS.listSnapshots);

    // Get ZFS properties for all dataset
    http.get(
        { path: '/servers/:server_uuid/dataset-properties',
          name: 'GetAllProperties' },
        before, ZFS.getAllProperties);

    // Get ZFS properties for a dataset
    http.get(
        { path: '/servers/:server_uuid/datasets/:dataset/properties',
          name: 'GetProperties' },
        before, ZFS.getProperties);

    // Set ZFS properties for a dataset
    http.post(
        { path: '/servers/:server_uuid/datasets/:dataset/properties',
          name: 'SetProperties' },
        before, ZFS.setProperties);

    // Destroy ZFS dataset
    http.del(
        { path: '/servers/:server_uuid/datasets/:dataset',
          name: 'DestroyDataset' },
        before, ZFS.destroyDataset);

    // List ZFS pools on a server
    http.get(
        { path: '/servers/:server_uuid/zpools', name: 'ListZpools' },
        before, ZFS.listZpools);
}

exports.attachTo = attachTo;
<|endoftext|>


<commit_before>import React from 'react'

import { Link } from 'react-router'
let EasyInputComponent = require("./EasyInputComponent");

import SearchResults from "./SearchResults";
import KeepWatching from "./KeepWatching";
let SettingsComponent = require("./Settings");

class Home extends EasyInputComponent {

  constructor(props) {
    super(props);
    this.state = { showSettings: false, hasOfflineVideos: false, hideSettings: !(window.maestroSettings && window.maestroSettings.NEVER_HIDE_SETTINGS) };
  }

  componentWillMount() {
    if (!this.props.authTokenManager.isAuthenticated() && this.props.router.location.pathname != "/login") {
      this.props.router.push("/login");
    } else if (!this.props.authTokenManager.isProfileSet() && this.props.router.location.pathname != "/profile") {
      this.props.router.push("/profile");
    }

    this.props.videoLoader.setRouter(this.props.router);

    document.addEventListener("maestro-load-video", (event) => {
      event = event.detail;
      //this.props.videoLoader.loadVideo(event.type, event.folder, event.index);
      this.props.router.push(`/view?type=${event.type}&index=${event.index}&folder=${event.folder}`);
    });

    document.addEventListener("maestro-offline-change", (event) => {
      event = event.detail;
      //this.props.videoLoader.loadVideo(event.type, event.folder, event.index);
      this.setState({ hasOfflineVideos: event.offline });
    });

    document.addEventListener("mousemove", this.showSettingsTemporarily.bind(this));
    document.body.addEventListener('click', this.showSettingsTemporarily.bind(this), true);
  }

  showSettingsTemporarily() {
    if (window.maestroSettings && window.maestroSettings.NEVER_HIDE_SETTINGS) {
      return;
    }
    this.setState({ hideSettings: false });
    if (this.hideSettingsTimeout) {
      window.clearTimeout(this.hideSettingsTimeout);
    }

    this.hideSettingsTimeout = window.setTimeout(() => {
      this.setState({ hideSettings: true });
    }, 5000);
  }

  goHome() {
    this.props.router.push("/");
  }

  render() {
    let settingsView = this.state.showSettings ?
      <SettingsComponent router={this.props.router} remoteController={this.props.remoteController} webSocketSender={this.props.webSocketSender} settingsManager={this.props.settingsManager} />
      : null;
    let settingsDisplay = this.state.hideSettings ? "none" : "block";

    let homeButton = null;
    if (["/login", "/profile", "/remote"].includes(this.props.router.location.pathname)) {
      settingsDisplay = "none";
    } else if (!["/"].includes(this.props.router.location.pathname)) {
      homeButton = <button className="maestroButton fa fa-home" onClick={evt => this.goHome()}></button>;
    }

    let settingsSection =

        <button class="cast-button" is="google-cast-button"></button>
        {homeButton}
        <button className="maestroButton fa fa-cog" onClick={this.toggleSetting} name="showSettings"></button>

      {settingsView}

;

    let offlineLink = null;
    if (this.props.offlineStorage.hasOfflineVideos()) {
      offlineLink =
<Link className="nostyle" to="offline">Offline Videos</Link>
;
    }

    let remoteLink = (this.props.settingsManager.get("playToRemoteClient") && this.props.settingsManager.get("playToRemoteClient") != "") ?
      <Link className="nostyle" to="remote">Remote Control</Link>
      : null;
    var body = this.props.children ||

        <SearchResults
          episodeLoader={this.props.episodeLoader}
          offlineStorage={this.props.offlineStorage}
          collectionsManager={this.props.collectionsManager}
          imageRoot={this.props.imageRoot}
          router={this.props.router}
          videoLoader={this.props.videoLoader}
          searcher={this.props.searcher}
          cacheProvider={this.props.cacheProvider}
          showProgressProvider={this.props.showProgressProvider} />

        <KeepWatching imageRoot={this.props.imageRoot} router={this.props.router} videoLoader={this.props.videoLoader} searcher={this.props.searcher} cacheProvider={this.props.cacheProvider} showProgressProvider={this.props.showProgressProvider} />

<Link className="nostyle" to="videos">Browse the collection</Link>

{remoteLink}

      {offlineLink}

;
    return (

{settingsSection}{body}

    )
  }
}

module.exports = Home
<commit_msg>always show offline videos link<commit_after>import React from 'react'

import { Link } from 'react-router'
let EasyInputComponent = require("./EasyInputComponent");

import SearchResults from "./SearchResults";
import KeepWatching from "./KeepWatching";
let SettingsComponent = require("./Settings");

class Home extends EasyInputComponent {

  constructor(props) {
    super(props);
    this.state = { showSettings: false, hasOfflineVideos: false, hideSettings: !(window.maestroSettings && window.maestroSettings.NEVER_HIDE_SETTINGS) };
  }

  componentWillMount() {
    if (!this.props.authTokenManager.isAuthenticated() && this.props.router.location.pathname != "/login") {
      this.props.router.push("/login");
    } else if (!this.props.authTokenManager.isProfileSet() && this.props.router.location.pathname != "/profile") {
      this.props.router.push("/profile");
    }

    this.props.videoLoader.setRouter(this.props.router);

    document.addEventListener("maestro-load-video", (event) => {
      event = event.detail;
      //this.props.videoLoader.loadVideo(event.type, event.folder, event.index);
      this.props.router.push(`/view?type=${event.type}&index=${event.index}&folder=${event.folder}`);
    });

    document.addEventListener("maestro-offline-change", (event) => {
      event = event.detail;
      //this.props.videoLoader.loadVideo(event.type, event.folder, event.index);
      this.setState({ hasOfflineVideos: event.offline });
    });

    document.addEventListener("mousemove", this.showSettingsTemporarily.bind(this));
    document.body.addEventListener('click', this.showSettingsTemporarily.bind(this), true);
  }

  showSettingsTemporarily() {
    if (window.maestroSettings && window.maestroSettings.NEVER_HIDE_SETTINGS) {
      return;
    }
    this.setState({ hideSettings: false });
    if (this.hideSettingsTimeout) {
      window.clearTimeout(this.hideSettingsTimeout);
    }

    this.hideSettingsTimeout = window.setTimeout(() => {
      this.setState({ hideSettings: true });
    }, 5000);
  }

  goHome() {
    this.props.router.push("/");
  }

  render() {
    let settingsView = this.state.showSettings ?
      <SettingsComponent router={this.props.router} remoteController={this.props.remoteController} webSocketSender={this.props.webSocketSender} settingsManager={this.props.settingsManager} />
      : null;
    let settingsDisplay = this.state.hideSettings ? "none" : "block";

    let homeButton = null;
    if (["/login", "/profile", "/remote"].includes(this.props.router.location.pathname)) {
      settingsDisplay = "none";
    } else if (!["/"].includes(this.props.router.location.pathname)) {
      homeButton = <button className="maestroButton fa fa-home" onClick={evt => this.goHome()}></button>;
    }

    let settingsSection =

        <button class="cast-button" is="google-cast-button"></button>
        {homeButton}
        <button className="maestroButton fa fa-cog" onClick={this.toggleSetting} name="showSettings"></button>

      {settingsView}

;

    let offlineLink = null;
    if (this.props.offlineStorage.canStoreOffline()) {
      offlineLink =
<Link className="nostyle" to="offline">Offline Videos</Link>
;
    }

    let remoteLink = (this.props.settingsManager.get("playToRemoteClient") && this.props.settingsManager.get("playToRemoteClient") != "") ?
      <Link className="nostyle" to="remote">Remote Control</Link>
      : null;
    var body = this.props.children ||

        <SearchResults
          episodeLoader={this.props.episodeLoader}
          offlineStorage={this.props.offlineStorage}
          collectionsManager={this.props.collectionsManager}
          imageRoot={this.props.imageRoot}
          router={this.props.router}
          videoLoader={this.props.videoLoader}
          searcher={this.props.searcher}
          cacheProvider={this.props.cacheProvider}
          showProgressProvider={this.props.showProgressProvider} />

        <KeepWatching imageRoot={this.props.imageRoot} router={this.props.router} videoLoader={this.props.videoLoader} searcher={this.props.searcher} cacheProvider={this.props.cacheProvider} showProgressProvider={this.props.showProgressProvider} />

<Link className="nostyle" to="videos">Browse the collection</Link>

{remoteLink}

      {offlineLink}

;
    return (

{settingsSection}{body}

    )
  }
}

module.exports = Home
<|endoftext|>


<commit_before>var smoothScroll = require('smoothscroll');

(function (document) {

  var Collapsible = {

    /**
     * Initialise the Collapse behaviour
     * @param {array} elems - array of HTMLCollections representing collapsible elements
     * @param {object} toggle - the element to be used as a toggle. If `null`, one is created
     * @param {bool} collapsed - if `true`, panel is collapsed by default
     */
    init: function(elems, toggle, collapsed) {
      for (var i = 0; i < elems.length; i++) {
        var toggleElem = toggle ? toggle.item(i) : null;
        this.initPanel(elems[i], collapsed);
        this.initToggle(elems[i], toggleElem);
      }
    },

    /**
     * Initialise the collapsible panel by setting its ID & 'aria-expanded' attributes
     * @param {object} elem - the containing DOMElement
     * @param {bool} collapsed - if `true`, panel is collapsed by default
     */
    initPanel: function(elem, collapsed) {
      var panelLabel = elem.dataset ? elem.dataset.label ? elem.dataset.label : elem.className : elem.className;

      elem.id = panelLabel;

      if (collapsed) {
        elem.setAttribute('aria-expanded', 'false');
      }
    },

    /**
     * Create a toggle element, attach an event listener and insert it into the DOM
     * @param {object} elem - containing element for collapsible nav
     */
    initToggle: function(elem, toggle) {
      var panelLabel = elem.dataset ? elem.dataset.label ? elem.dataset.label : elem.className : elem.className,
          toggleElem = toggle || document.createElement('button'),
          self = this;

      // console.log(panelLabel, toggle);

      toggleElem.setAttribute('aria-controls', panelLabel);
      toggleElem.className = panelLabel + '-toggle';
      toggleElem.textContent = elem.dataset.toggleLabel || 'Menu';
      toggleElem.targetElem = elem;
      toggleElem.addEventListener('click', self.togglePanel);

      if (!toggle) {
        elem.parentNode.insertBefore(toggleElem, elem);
      }

    },

    /**
     * Toggles ARIA attribute on the nav element
     * @param {event} event - the event that triggered the toggle
     */
    togglePanel: function(event) {
      var toggle = event.target,
          elem = event.target.targetElem,
          expanded = elem.getAttribute('aria-expanded') === 'true';

      event.preventDefault();

      if (elem.hasAttribute('open')) {
        elem.removeAttribute('open');
      } else {
        elem.setAttribute('open', '');
      }

      toggle.setAttribute('aria-expanded', expanded ? 'false' : 'true');
      elem.setAttribute('aria-expanded', expanded ? 'false' : 'true');
    }

  };

  // Kick of the JavaScript party when the DOM is ready
  document.addEventListener('DOMContentLoaded', function() {
    var navElements = document.querySelectorAll('.global-nav, .local-nav');
    Collapsible.init(navElements, null, true);

    var accordionElements = document.querySelectorAll('.accordion, details'),
        accordionToggleElement = document.querySelectorAll('.accordion-button, summary');
    Collapsible.init(accordionElements, accordionToggleElement, false);
  });

})(document);

// This code is legacy as of v1.2
// Marked for removal in v2.0
$(document).ready(function () {
    $('.js-accordion-trigger').bind('touchstart click', function (e) {

        jQuery(this).parent().find('ul').slideToggle('fast');
        jQuery(this).find(".chevron").toggleClass('top bottom');
        // apply the toggle to the ul
        jQuery(this).parent().toggleClass('is-expanded');

        // https://www.w3.org/WAI/GL/wiki/Using_the_WAI-ARIA_aria-expanded_state_to_mark_expandable_and_collapsible_regions
        if (jQuery(this).attr('aria-expanded') == 'false') { // region is collapsed
            // update the aria-expanded attribute of the region
            jQuery(this).attr('aria-expanded', 'true');
            // move focus to the region
            jQuery(this).find('ul').focus();
            jQuery(this).find('span').text("Show menu");
        }
        else { // region is expanded
            // update the aria-expanded attribute of the region
            jQuery(this).attr('aria-expanded', 'false');
            jQuery(this).find('span').text("Hide menu");
        }

        e.preventDefault();
    });
});
<commit_msg>Only update the textContent of a Collapsible toggle if it's a Menu<commit_after>var smoothScroll = require('smoothscroll');

(function (document) {

  var Collapsible = {

    /**
     * Initialise the Collapse behaviour
     * @param {array} elems - array of HTMLCollections representing collapsible elements
     * @param {object} toggle - the element to be used as a toggle. If `null`, one is created
     * @param {bool} collapsed - if `true`, panel is collapsed by default
     */
    init: function(elems, toggle, collapsed) {
      for (var i = 0; i < elems.length; i++) {
        var toggleElem = toggle ? toggle.item(i) : null;
        this.initPanel(elems[i], collapsed);
        this.initToggle(elems[i], toggleElem);
      }
    },

    /**
     * Initialise the collapsible panel by setting its ID & 'aria-expanded' attributes
     * @param {object} elem - the containing DOMElement
     * @param {bool} collapsed - if `true`, panel is collapsed by default
     */
    initPanel: function(elem, collapsed) {
      var panelLabel = elem.dataset ? elem.dataset.label ? elem.dataset.label : elem.className : elem.className;

      elem.id = panelLabel;

      if (collapsed) {
        elem.setAttribute('aria-expanded', 'false');
      }
    },

    /**
     * Create a toggle element, attach an event listener and insert it into the DOM
     * @param {object} elem - containing element for collapsible nav
     */
    initToggle: function(elem, toggle) {
      var panelLabel = elem.dataset ? elem.dataset.label ? elem.dataset.label : elem.className : elem.className,
          toggleElem = toggle || document.createElement('button'),
          self = this;

      // console.log(panelLabel, toggle);
      if (!toggle) {
          toggleElem.textContent = elem.dataset.toggleLabel || 'Menu';
      }

      toggleElem.setAttribute('aria-controls', panelLabel);
      toggleElem.className = panelLabel + '-toggle';
      toggleElem.targetElem = elem;
      toggleElem.addEventListener('click', self.togglePanel);

      if (!toggle) {
        elem.parentNode.insertBefore(toggleElem, elem);
      }

    },

    /**
     * Toggles ARIA attribute on the nav element
     * @param {event} event - the event that triggered the toggle
     */
    togglePanel: function(event) {
      var toggle = event.target,
          elem = event.target.targetElem,
          expanded = elem.getAttribute('aria-expanded') === 'true';

      event.preventDefault();

      if (elem.hasAttribute('open')) {
        elem.removeAttribute('open');
      } else {
        elem.setAttribute('open', '');
      }

      toggle.setAttribute('aria-expanded', expanded ? 'false' : 'true');
      elem.setAttribute('aria-expanded', expanded ? 'false' : 'true');
    }

  };

  // Kick of the JavaScript party when the DOM is ready
  document.addEventListener('DOMContentLoaded', function() {
    var navElements = document.querySelectorAll('.global-nav, .local-nav');
    Collapsible.init(navElements, null, true);

    var accordionElements = document.querySelectorAll('.accordion, details'),
        accordionToggleElement = document.querySelectorAll('.accordion-button, summary');
    Collapsible.init(accordionElements, accordionToggleElement, false);
  });

})(document);

// This code is legacy as of v1.2
// Marked for removal in v2.0
$(document).ready(function () {
    $('.js-accordion-trigger').bind('touchstart click', function (e) {

        jQuery(this).parent().find('ul').slideToggle('fast');
        jQuery(this).find(".chevron").toggleClass('top bottom');
        // apply the toggle to the ul
        jQuery(this).parent().toggleClass('is-expanded');

        // https://www.w3.org/WAI/GL/wiki/Using_the_WAI-ARIA_aria-expanded_state_to_mark_expandable_and_collapsible_regions
        if (jQuery(this).attr('aria-expanded') == 'false') { // region is collapsed
            // update the aria-expanded attribute of the region
            jQuery(this).attr('aria-expanded', 'true');
            // move focus to the region
            jQuery(this).find('ul').focus();
            jQuery(this).find('span').text("Show menu");
        }
        else { // region is expanded
            // update the aria-expanded attribute of the region
            jQuery(this).attr('aria-expanded', 'false');
            jQuery(this).find('span').text("Hide menu");
        }

        e.preventDefault();
    });
});
<|endoftext|>


<commit_before>(function() {
    hljs.tabReplace = '    ';

    var socket = io.connect(getSocketUrl() + '/game');

    var GameState = function() {
        this.gameStatus = ko.observable('Waiting for players...');
        this.gameStatusCss = ko.observable('');
        this.countdown = ko.observable(0);
        this.countdownRunning = ko.observable(false);
        this.started = ko.observable(false);
        this.gamecode = ko.observable('');
        this.langCss = ko.observable('');
    };

    var viewModel = {
        game: new GameState()
    };

    ko.applyBindings(viewModel);

    var $gamecode = null;

    var game = null;
    var exercise = null;
    var nonTypeables = null;

    var code = null;
    var currentPos = 0;
    var $currentChar = null;

    var isTextNode = function(elem) {
        return elem.nodeType === 3;
    };

    var bindCodeCharacters = function() {
        var searchPattern = /(.)([ \t]*\n\s*)|([ \t]*\n\s*)(.)|(.)/g;
        var newlinePattern = /^[ \t]*\n\s*$/g;
        var returnSymbol = '';

        var replacer = function(str, $1, $2, $3, $4, $5) {
            $1 = $1 || '';
            $2 = $2 || '';
            $3 = $3 || '';
            $4 = $4 || '';
            $5 = $5 || '';

            // If newline groups matched anything, add the
            // return symbol to the match
            if ($2) {
                $2 = returnSymbol + $2;
            }
            if ($3) {
                $3 = returnSymbol + $3;
            }
            return $3 + '' + $1 + $4 + $5 + '' + $2;
        };

        $gamecode = $('#gamecode');

        var nonWhitespaceFound = false;
        var $contents = $gamecode.contents();
        $contents.each(function(i) {
            var $this = $(this);

            if ($this.is(nonTypeables)) {
                return;
            }

            var text = $this.text(),
                parts, prefix = '', addon = '';
            if (isTextNode(this)) {
                if (nonWhitespaceFound) {
                    if (i > 0 && $contents.eq(i - 1).is(nonTypeables)) {
                        parts = (/(\s+)((?:.|\n)*)$/g).exec(text);
                        if (parts) {
                            text = parts[2];
                            prefix = parts[1];
                        }
                    }
                    if (text.match(newlinePattern)) {
                        $this.replaceWith(returnSymbol + text);
                        return;
                    }
                    if (i < $contents.length - 1 && $contents.eq(i + 1).is(nonTypeables)) {
                        parts = (/^((?:.|\n)*)([ \t]+)$/g).exec(text);
                        if (parts) {
                            text = parts[1];
                            addon = returnSymbol + parts[2];
                        }
                    }
                    if (i === $contents.length - 1 && !text.match(/[^\s][ \t]*\n\s*$/)) {
                        addon = returnSymbol;
                    }

                    $this.replaceWith(prefix + text.replace(searchPattern, replacer) + addon);
                    prefix = '';
                    addon = '';
                } else {
                    if (text.trim().length === 0) {
                        return;
                    }
                    $this.replaceWith(text.replace(searchPattern, replacer));
                    nonWhitespaceFound = true;
                }
            } else {
                var oldClass = $this.attr('class');
                var $newContent = $(text.replace(searchPattern, replacer));
                $this.replaceWith($newContent);
                $newContent.addClass(oldClass);
                nonWhitespaceFound = true;
            }
        });

        $gamecode.find('.code-char').addClass('untyped');
    };

    var pingId = null;
    var pingWaiting = function() {
        socket.emit('ingame:ping', { gameId: game._id });
        pingId = setTimeout(pingWaiting, 500);
    };

    var fullyStarted = false;
    var fullyStarting = false;
    var startGame = function() {
        if (fullyStarted) {
            return;
        }
        viewModel.game.gameStatus('Go!');
        viewModel.game.gameStatusCss('text-info control-panel-go');
        fullyStarted = true;
    };

    var setStarting = function() {
        if (fullyStarting) {
            return;
        }
        viewModel.game.gameStatus('Get ready... ');

        if (!$currentChar) {
            $currentChar = $gamecode.find('.code-char').first();
            $currentChar.addClass('player');
        }
    };

    var resetStarting = function() {
        if ($currentChar) {
            $currentChar.removeClass('player');
            $currentChar = null;
        }
    };

    var wrapFullyStarted = function(fn) {
        return function() {
            if (fullyStarted) {
                fn.apply(this, arguments);
            }
        };
    };

    // Bind key events
    var keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    keys = keys.concat(_.map(keys, function(k) { return k.toUpperCase(); }));
    keys = keys.concat(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']);
    keys = keys.concat(['`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', '\\', '|', '\'', '"', ';', ':', '/', '?', '.', '>', ',', '<']);
    keys = keys.concat(['enter', 'space', 'shift+space']);

    Mousetrap.bind(keys, wrapFullyStarted(function(e, key) {
        e.preventDefault();

        log(key);

        key = key === 'space' ? ' ' :
              key === 'shift+space' ? ' ' :
              key === 'enter' ? '\n' :
              key;

        if (key === code.charAt(currentPos)) {
            // TODO: Add completion detection
            currentPos++;
            $currentChar.removeClass('player untyped');
            $currentChar.addClass('typed');

            $currentChar = $currentChar.nextAll('.code-char').first();
            $currentChar.addClass('player');
        }
        // TODO: Add incorrect key handling
    }));

    Mousetrap.bind('backspace', wrapFullyStarted(function(e, key) {
        e.preventDefault();
        // TODO: Add backspace handling
    }));

    socket.on('ingame:ready:res', function(data) {
        console.log('received ingame:ready:res');
        game = data.game;
        exercise = data.exercise;
        code = data.exercise.typeableCode;
        nonTypeables = data.nonTypeables;
        swiftcode.game = data.game;
        swiftcode.exercise = data.exercise;
        viewModel.game.gamecode(data.exercise.code);
        viewModel.game.langCss('language-' + data.game.lang);

        hljs.initHighlighting();
        bindCodeCharacters();
        pingWaiting();
    });

    socket.on('ingame:ping:res', function(data) {
        console.log('received ingame:ping:res');
        game = data.game;
        viewModel.game.countdownRunning(game.starting);
        viewModel.game.started(game.started);
        if (game.starting) {
            setStarting();
            viewModel.game.countdown(moment(game.startTime).diff(moment(), 'seconds') + 1);

            var millisecondsLeft = moment(game.startTime).diff(moment());
            if (millisecondsLeft < 1000) {
                setTimeout(startGame, millisecondsLeft);
            }
        } else {
            viewModel.game.gameStatus('Waiting for players...');
            resetStarting();
        }

        if (game.started) {
            clearTimeout(pingId);
            startGame();
        }
    });

    console.log('emit ingame:ready');
    socket.emit('ingame:ready', { player: user._id });
})();
<commit_msg>Add some TODOs in game.js<commit_after>(function() {
    hljs.tabReplace = '    ';

    var socket = io.connect(getSocketUrl() + '/game');

    var GameState = function() {
        this.gameStatus = ko.observable('Waiting for players...');
        this.gameStatusCss = ko.observable('');
        this.countdown = ko.observable(0);
        this.countdownRunning = ko.observable(false);
        this.started = ko.observable(false);
        this.gamecode = ko.observable('');
        this.langCss = ko.observable('');
    };

    var viewModel = {
        game: new GameState()
    };

    ko.applyBindings(viewModel);

    var $gamecode = null;

    var game = null;
    var exercise = null;
    var nonTypeables = null;

    var code = null;
    var currentPos = 0;
    var $currentChar = null;

    var isTextNode = function(elem) {
        return elem.nodeType === 3;
    };

    var bindCodeCharacters = function() {
        var searchPattern = /(.)([ \t]*\n\s*)|([ \t]*\n\s*)(.)|(.)/g;
        var newlinePattern = /^[ \t]*\n\s*$/g;
        var returnSymbol = '';

        var replacer = function(str, $1, $2, $3, $4, $5) {
            $1 = $1 || '';
            $2 = $2 || '';
            $3 = $3 || '';
            $4 = $4 || '';
            $5 = $5 || '';

            // If newline groups matched anything, add the
            // return symbol to the match
            if ($2) {
                $2 = returnSymbol + $2;
            }
            if ($3) {
                $3 = returnSymbol + $3;
            }
            return $3 + '' + $1 + $4 + $5 + '' + $2;
        };

        $gamecode = $('#gamecode');

        var nonWhitespaceFound = false;
        var $contents = $gamecode.contents();
        $contents.each(function(i) {
            var $this = $(this);

            if ($this.is(nonTypeables)) {
                return;
            }

            var text = $this.text(),
                parts, prefix = '', addon = '';
            if (isTextNode(this)) {
                if (nonWhitespaceFound) {
                    if (i > 0 && $contents.eq(i - 1).is(nonTypeables)) {
                        parts = (/(\s+)((?:.|\n)*)$/g).exec(text);
                        if (parts) {
                            text = parts[2];
                            prefix = parts[1];
                        }
                    }
                    if (text.match(newlinePattern)) {
                        $this.replaceWith(returnSymbol + text);
                        return;
                    }
                    if (i < $contents.length - 1 && $contents.eq(i + 1).is(nonTypeables)) {
                        parts = (/^((?:.|\n)*)([ \t]+)$/g).exec(text);
                        if (parts) {
                            text = parts[1];
                            addon = returnSymbol + parts[2];
                        }
                    }
                    if (i === $contents.length - 1 && !text.match(/[^\s][ \t]*\n\s*$/)) {
                        addon = returnSymbol;
                    }

                    $this.replaceWith(prefix + text.replace(searchPattern, replacer) + addon);
                    prefix = '';
                    addon = '';
                } else {
                    if (text.trim().length === 0) {
                        return;
                    }
                    $this.replaceWith(text.replace(searchPattern, replacer));
                    nonWhitespaceFound = true;
                }
            } else {
                var oldClass = $this.attr('class');
                var $newContent = $(text.replace(searchPattern, replacer));
                $this.replaceWith($newContent);
                $newContent.addClass(oldClass);
                nonWhitespaceFound = true;
            }
        });

        $gamecode.find('.code-char').addClass('untyped');
    };

    // TODO: Try different method? Using char -> element mapping,
    // collapse chars into single string, modify the string, and normalize
    // it to typeables

    var pingId = null;
    var pingWaiting = function() {
        socket.emit('ingame:ping', { gameId: game._id });
        pingId = setTimeout(pingWaiting, 500);
    };

    // TODO: Add T-minus countdown, and running time clock
    // TODO: Fix timing; don't wait for ping, set a timeout
    var fullyStarted = false;
    var fullyStarting = false;
    var startGame = function() {
        if (fullyStarted) {
            return;
        }
        viewModel.game.gameStatus('Go!');
        viewModel.game.gameStatusCss('text-info control-panel-go');
        fullyStarted = true;
    };

    var setStarting = function() {
        if (fullyStarting) {
            return;
        }
        viewModel.game.gameStatus('Get ready... ');

        if (!$currentChar) {
            $currentChar = $gamecode.find('.code-char').first();
            $currentChar.addClass('player');
        }
    };

    var resetStarting = function() {
        if ($currentChar) {
            $currentChar.removeClass('player');
            $currentChar = null;
        }
    };

    var wrapFullyStarted = function(fn) {
        return function() {
            if (fullyStarted) {
                fn.apply(this, arguments);
            }
        };
    };

    // Bind key events
    var keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
    keys = keys.concat(_.map(keys, function(k) { return k.toUpperCase(); }));
    keys = keys.concat(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']);
    keys = keys.concat(['`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', '\\', '|', '\'', '"', ';', ':', '/', '?', '.', '>', ',', '<']);
    keys = keys.concat(['enter', 'space', 'shift+space']);

    Mousetrap.bind(keys, wrapFullyStarted(function(e, key) {
        e.preventDefault();

        log(key);

        key = key === 'space' ? ' ' :
              key === 'shift+space' ? ' ' :
              key === 'enter' ? '\n' :
              key;

        if (key === code.charAt(currentPos)) {
            // TODO: Add completion detection
            currentPos++;
            $currentChar.removeClass('player untyped');
            $currentChar.addClass('typed');

            $currentChar = $currentChar.nextAll('.code-char').first();
            $currentChar.addClass('player');
        }
        // TODO: Add incorrect key handling
    }));

    Mousetrap.bind('backspace', wrapFullyStarted(function(e, key) {
        e.preventDefault();
        // TODO: Add backspace handling
    }));

    socket.on('ingame:ready:res', function(data) {
        console.log('received ingame:ready:res');
        game = data.game;
        exercise = data.exercise;
        code = data.exercise.typeableCode;
        nonTypeables = data.nonTypeables;
        swiftcode.game = data.game;
        swiftcode.exercise = data.exercise;
        viewModel.game.gamecode(data.exercise.code);
        viewModel.game.langCss('language-' + data.game.lang);

        hljs.initHighlighting();
        bindCodeCharacters();
        pingWaiting();
    });

    socket.on('ingame:ping:res', function(data) {
        console.log('received ingame:ping:res');
        game = data.game;
        viewModel.game.countdownRunning(game.starting);
        viewModel.game.started(game.started);
        if (game.starting) {
            setStarting();
            viewModel.game.countdown(moment(game.startTime).diff(moment(), 'seconds') + 1);

            var millisecondsLeft = moment(game.startTime).diff(moment());
            if (millisecondsLeft < 1000) {
                setTimeout(startGame, millisecondsLeft);
            }
        } else {
            viewModel.game.gameStatus('Waiting for players...');
            resetStarting();
        }

        if (game.started) {
            clearTimeout(pingId);
            startGame();
        }
    });

    console.log('emit ingame:ready');
    socket.emit('ingame:ready', { player: user._id });
})();
<|endoftext|>


<commit_before>(function() {

'use strict';

var _    = require('underscore');
var uint = require('uint-js');
var util = require('../util');

var ethernet = require('../ethernet');
var ipv4     = require('../ipv4');

var Masks = {
  in_port:  new uint.UInt({ bytes: 4, value: 0x00000001 }),
  dl_vlan:  new uint.UInt({ bytes: 4, value: 0x00000002 }),
  dl_src:   new uint.UInt({ bytes: 4, value: 0x00000004 }),
  dl_dst:   new uint.UInt({ bytes: 4, value: 0x00000008 }),
  dl_type:  new uint.UInt({ bytes: 4, value: 0x00000010 }),
  nw_proto: new uint.UInt({ bytes: 4, value: 0x00000020 }),
  tp_src:   new uint.UInt({ bytes: 4, value: 0x00000040 }),
  tp_dst:   new uint.UInt({ bytes: 4, value: 0x00000080 }),
  nw_src:   new uint.UInt({ bytes: 4, value: 0x00000000 }),
  nw_dst:   new uint.UInt({ bytes: 4, value: 0x00000000 }),
  dl_pcp:   new uint.UInt({ bytes: 4, value: 0x00100000 }),
  nw_tos:   new uint.UInt({ bytes: 4, value: 0x00200000 }),
  all:      new uint.UInt({ bytes: 4, value: 0x003fffff })
};

function Match(args) {
  // Establish the default values
  this.wildcards = new uint.UInt({ bytes: 4 });
  this.in_port   = new uint.UInt({ bytes: 2 });
  this.dl_src    = new ethernet.MAC();
  this.dl_dst    = new ethernet.MAC();
  this.dl_vlan   = new uint.UInt({ bytes: 2 });
  this.dl_pcp    = new uint.UInt({ bytes: 1 });
  this.dl_type   = new uint.UInt({ bytes: 2 });
  this.nw_tos    = new uint.UInt({ bytes: 1 });
  this.nw_proto  = new uint.UInt({ bytes: 1 });
  this.nw_src    = new ipv4.Address();
  this.nw_dst    = new ipv4.Address();
  this.tp_src    = new uint.UInt({ bytes: 2 });
  this.tp_dst    = new uint.UInt({ bytes: 2 });
  // Establish any parameters that may have been passed
  _(args).each(function(value, key) {
    if(_(this).has(key)) {
      if(value === '*') {
        this.wildcards.or(Masks[key]);
      } else if(/\//.test(value)) {
        var match = value.splict('/');
        this[key].value(match[0]);
        this.wildcards.or();
      } else {
        this[key].value(value);
      }
    }
  });
}
exports.Match = Match;

Match.prototype.toView = function(view) {
  if(view.available() < this.bytes()) {
    throw util.Available();
  }
  view.writeUInt32(this.wildcards);
  view.writeUInt16(this.in_port);
  this.dl_src.toView(view);
  this.dl_dst.toView(view);
  view.writeUInt16(this.dl_vlan);
  view.writeUInt8(this.dl_pcp);
  util.pad(view, 1);
  view.writeUInt16(this.dl_type);
  view.writeUInt8(this.nw_tos);
  view.writeUInt8(this.nw_proto);
  util.pad(view, 2);
  this.nw_src.toView(view);
  this.nw_dst.toView(view);
  view.writeUInt16(this.tp_src);
  view.writeUInt16(this.tp_dst);
};

Match.prototype.fromView = function(view) {
  if(view.available() < this.bytes()) {
    throw util.Available('Match');
  }
  this.wildcards = view.readUInt32();
  this.in_port  = view.readUInt16();
  this.dl_src.fromView(view);
  this.dl_dst.fromView(view);
  this.dl_vlan = view.readUInt16();
  this.dl_pcp = view.readUInt8();
  util.pad(view, 1);
  this.dl_type = view.readUInt16();
  this.nw_tos = view.readUInt8();
  this.nw_proto = view.readUInt8();
  util.pad(view, 2);
  this.nw_src.fromView(view);
  this.nw_dst.fromView(view);
  this.tp_src = view.readUInt16();
  this.tp_dst = view.readUInt16();
};

Match.prototype.toString = function(){
  return {
    wildcards: this.wildcards.toString(16),
    in_port: this.in_port.toString(16),
    dl_src: this.dl_src.toString(16),
    dl_dst: this.dl_dst.toString(16),
    dl_vlan: this.dl_vlan.toString(16),
    dl_pcp: this.dl_pcp.toString(16),
    dl_type: this.dl_type.toString(16),
    nw_tos: this.nw_tos.toString(16),
    nw_proto: this.nw_proto.toString(16),
    nw_src: this.nw_src.toString(16),
    nw_dst: this.nw_dst.toString(16),
    tp_src: this.tp_src.toString(16),
    tp_dst: this.tp_dst.toString(16)
  };
};

Match.prototype.bytes = function(){
  return 40;
};

})();
<commit_msg>match update<commit_after>(function() {

'use strict';

var _    = require('underscore');
var uint = require('uint-js');
var util = require('../util');

var ethernet = require('../ethernet');
var ipv4     = require('../ipv4');

var Masks = {
  in_port:  new uint.UInt({ bytes: 4, value: 0x00000001 }),
  dl_vlan:  new uint.UInt({ bytes: 4, value: 0x00000002 }),
  dl_src:   new uint.UInt({ bytes: 4, value: 0x00000004 }),
  dl_dst:   new uint.UInt({ bytes: 4, value: 0x00000008 }),
  dl_type:  new uint.UInt({ bytes: 4, value: 0x00000010 }),
  nw_proto: new uint.UInt({ bytes: 4, value: 0x00000020 }),
  tp_src:   new uint.UInt({ bytes: 4, value: 0x00000040 }),
  tp_dst:   new uint.UInt({ bytes: 4, value: 0x00000080 }),
  nw_src:   new uint.UInt({ bytes: 4, value: 0x00000000 }),
  nw_dst:   new uint.UInt({ bytes: 4, value: 0x00000000 }),
  dl_pcp:   new uint.UInt({ bytes: 4, value: 0x00100000 }),
  nw_tos:   new uint.UInt({ bytes: 4, value: 0x00200000 }),
  all:      new uint.UInt({ bytes: 4, value: 0x003fffff })
};

function Match(args) {
  // Establish the default values
  this.wildcards = new uint.UInt({ bytes: 4 });
  this.internal = {
    phy_port: new uint.UInt({ bytes: 2 })
  };
  this.ethernet = {
    src: new ethernet.MAC(),
    dst: new ethernet.MAC(),
    vlan: new uint.UInt({ bytes: 2 }),
    pcp:  new uint.UInt({ bytes: 1 }),
    type: new uint.UInt({ bytes: 2 })
  };
  this.ipv4 = {
    tos: new uint.UInt({ bytes: 1 }),
    proto: new uint.UInt({ bytes: 2 }),
    src: new ipv4.Address(),
    dst: new ipv4.Address()
  };
  this.transport = {
    src: new uint.UInt({ bytes: 2 }),
    dst: new uint.UInt({ bytes: 2 })
  };
  // Establish any parameters that may have been passed
  _(args).each(function(value, key) {
    if(_(this).has(key)) {
      if(value === '*') {
        this.wildcards.or(Masks[key]);
      } else if(/\//.test(value)) {
        var match = value.splict('/');
        this[key].value(match[0]);
        this.wildcards.or();
      } else {
        this[key].value(value);
      }
    }
  });
}
exports.Match = Match;

Match.prototype.toView = function(view) {
  if(view.available() < this.bytes()) {
    throw util.Available();
  }
  view.writeUInt32(this.wildcards);
  view.writeUInt16(this.internal.phy_port);
  this.ethernet.src.toView(view);
  this.ethernet.dst.toView(view);
  view.writeUInt16(this.ethernet.vlan);
  view.writeUInt8(this.ethernet.pcp);
  util.pad(view, 1);
  view.writeUInt16(this.ethernet.type);
  view.writeUInt8(this.ipv4.tos);
  view.writeUInt8(this.ipv4.proto);
  util.pad(view, 2);
  this.ipv4.src.toView(view);
  this.ipv4.dst.toView(view);
  view.writeUInt16(this.transport.src);
  view.writeUInt16(this.transport.dst);
};

Match.prototype.fromView = function(view) {
  if(view.available() < this.bytes()) {
    throw util.Available('Match');
  }
  this.wildcards = view.readUInt32();
  this.internal.phy_port = view.readUInt16();
  this.ethernet.src.fromView(view);
  this.ethernet.dst.fromView(view);
  this.ethernet.vlan= view.readUInt16();
  this.ethernet.pcp = view.readUInt8();
  util.pad(view, 1);
  this.ethernet.type = view.readUInt16();
  this.ipv4.tos = view.readUInt8();
  this.ipv4.proto = view.readUInt8();
  util.pad(view, 2);
  this.ipv4.src.fromView(view);
  this.ipv4.dst.fromView(view);
  this.transport.src = view.readUInt16();
  this.transport.dst = view.readUInt16();
};

Match.prototype.toString = function(){
  return {
    wildcards: this.wildcards.toString(16),
    in_port: this.in_port.toString(16),
    dl_src: this.dl_src.toString(16),
    dl_dst: this.dl_dst.toString(16),
    dl_vlan: this.dl_vlan.toString(16),
    dl_pcp: this.dl_pcp.toString(16),
    dl_type: this.dl_type.toString(16),
    nw_tos: this.nw_tos.toString(16),
    nw_proto: this.nw_proto.toString(16),
    nw_src: this.nw_src.toString(16),
    nw_dst: this.nw_dst.toString(16),
    tp_src: this.tp_src.toString(16),
    tp_dst: this.tp_dst.toString(16)
  };
};

Match.prototype.bytes = function(){
  return 40;
};

})();
<|endoftext|>