<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { isEqual } from 'lodash'
import * as ACTION_TYPES from '../constants/action_types'
import * as MAPPING_TYPES from '../constants/mapping_types'
import { selectParamsToken, selectParamsUsername, selectPost } from '../selectors'
import { loadComments, loadPostDetail, toggleLovers, toggleReposters } from '../actions/posts'
import { ErrorState4xx } from '../components/errors/Errors'
import { PostDetail, PostDetailError } from '../components/views/PostDetail'

// A lot of information needs to get generated in the meta tags for this page
// before it ever hits React's virtual DOM so it's really beneficial to
// optimzize the amount of times render is called.
export function shouldContainerUpdate(thisProps, nextProps) {
  const { author, isLoggedIn, paramsToken, paramsUsername,
    post, streamError, streamType } = thisProps
  if (!nextProps.author || !nextProps.post) {
    return false
  }
  if (paramsToken !== nextProps.paramsToken ||
      paramsUsername !== nextProps.paramsUsername ||
      isLoggedIn !== nextProps.isLoggedIn) {
    return true
  }
  if (!isEqual(author, nextProps.author) || !isEqual(post, nextProps.post)) {
    return true
  }
  if (streamType !== nextProps.streamType || !isEqual(streamError, nextProps.streamError)) {
    return true
  }
  return false
}

export function mapStateToProps(state, props) {
  const { authentication, json, stream } = state
  const paramsToken = selectParamsToken(state, props)
  const paramsUsername = selectParamsUsername(state, props)
  console.log('paramsUsername', paramsUsername)
  const post = selectPost(state, props)
  return {
    author: post ? json[MAPPING_TYPES.USERS][post.authorId] : null,
    isLoggedIn: authentication.isLoggedIn,
    paramsToken,
    paramsUsername,
    post,
    streamError: stream.error,
    streamType: stream.type,
  }
}

export class PostDetailContainer extends Component {

  static propTypes = {
    author: PropTypes.object,
    dispatch: PropTypes.func.isRequired,
    isLoggedIn: PropTypes.bool.isRequired,
    post: PropTypes.object,
    paramsToken: PropTypes.string.isRequired,
    paramsUsername: PropTypes.string.isRequired,
    streamError: PropTypes.object,
    streamType: PropTypes.string,
  }

  static preRender = (store, routerState) => {
    const params = routerState.params
    return store.dispatch(loadPostDetail(`~${params.token}`, `~${params.username}`))
  }

  componentWillMount() {
    const { dispatch, paramsToken, paramsUsername, post } = this.props
    if (post) {
      this.lovesWasOpen = post.showLovers
      this.repostsWasOpen = post.showReposters
    }
    dispatch(loadPostDetail(`~${paramsToken}`, `~${paramsUsername}`))
  }

  componentWillReceiveProps(nextProps) {
    const { dispatch, paramsToken, paramsUsername } = this.props
    if (paramsToken !== nextProps.paramsToken || paramsUsername !== nextProps.paramsUsername) {
      dispatch(loadPostDetail(`~${nextProps.paramsToken}`, `~${nextProps.paramsUsername}`))
    }
  }

  shouldComponentUpdate(nextProps) {
    return shouldContainerUpdate(this.props, nextProps)
  }

  componentWillUnmount() {
    const { dispatch, isLoggedIn, post } = this.props
    // this prevents the lover/reposters from firing since logout clears the json store
    if (!isLoggedIn) { return }
    if (!this.lovesWasOpen) {
      dispatch(toggleLovers(post, false))
    }
    if (!this.repostsWasOpen) {
      dispatch(toggleReposters(post, false))
    }
  }

  render() {
    const { author, paramsToken, post, streamError, streamType } = this.props
    if (streamType === ACTION_TYPES.POST.DETAIL_FAILURE && streamError && !post) {
      return (
        <PostDetailError>
          <ErrorState4xx />
        </PostDetailError>
      )
    }
    const props = {
      author,
      hasEditor: author && author.hasCommentingEnabled && !(post.isReposting || post.isEditing),
      key: `postDetail_${paramsToken}`,
      post,
      streamAction: author && author.hasCommentingEnabled ? loadComments(post, false) : null,
    }
    return <PostDetail {...props} />
  }
}

export default connect(mapStateToProps)(PostDetailContainer)

<commit_msg>Remove a console statement.<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { isEqual } from 'lodash'
import * as ACTION_TYPES from '../constants/action_types'
import * as MAPPING_TYPES from '../constants/mapping_types'
import { selectParamsToken, selectParamsUsername, selectPost } from '../selectors'
import { loadComments, loadPostDetail, toggleLovers, toggleReposters } from '../actions/posts'
import { ErrorState4xx } from '../components/errors/Errors'
import { PostDetail, PostDetailError } from '../components/views/PostDetail'

// A lot of information needs to get generated in the meta tags for this page
// before it ever hits React's virtual DOM so it's really beneficial to
// optimzize the amount of times render is called.
export function shouldContainerUpdate(thisProps, nextProps) {
  const { author, isLoggedIn, paramsToken, paramsUsername,
    post, streamError, streamType } = thisProps
  if (!nextProps.author || !nextProps.post) {
    return false
  }
  if (paramsToken !== nextProps.paramsToken ||
      paramsUsername !== nextProps.paramsUsername ||
      isLoggedIn !== nextProps.isLoggedIn) {
    return true
  }
  if (!isEqual(author, nextProps.author) || !isEqual(post, nextProps.post)) {
    return true
  }
  if (streamType !== nextProps.streamType || !isEqual(streamError, nextProps.streamError)) {
    return true
  }
  return false
}

export function mapStateToProps(state, props) {
  const { authentication, json, stream } = state
  const paramsToken = selectParamsToken(state, props)
  const paramsUsername = selectParamsUsername(state, props)
  const post = selectPost(state, props)
  return {
    author: post ? json[MAPPING_TYPES.USERS][post.authorId] : null,
    isLoggedIn: authentication.isLoggedIn,
    paramsToken,
    paramsUsername,
    post,
    streamError: stream.error,
    streamType: stream.type,
  }
}

export class PostDetailContainer extends Component {

  static propTypes = {
    author: PropTypes.object,
    dispatch: PropTypes.func.isRequired,
    isLoggedIn: PropTypes.bool.isRequired,
    post: PropTypes.object,
    paramsToken: PropTypes.string.isRequired,
    paramsUsername: PropTypes.string.isRequired,
    streamError: PropTypes.object,
    streamType: PropTypes.string,
  }

  static preRender = (store, routerState) => {
    const params = routerState.params
    return store.dispatch(loadPostDetail(`~${params.token}`, `~${params.username}`))
  }

  componentWillMount() {
    const { dispatch, paramsToken, paramsUsername, post } = this.props
    if (post) {
      this.lovesWasOpen = post.showLovers
      this.repostsWasOpen = post.showReposters
    }
    dispatch(loadPostDetail(`~${paramsToken}`, `~${paramsUsername}`))
  }

  componentWillReceiveProps(nextProps) {
    const { dispatch, paramsToken, paramsUsername } = this.props
    if (paramsToken !== nextProps.paramsToken || paramsUsername !== nextProps.paramsUsername) {
      dispatch(loadPostDetail(`~${nextProps.paramsToken}`, `~${nextProps.paramsUsername}`))
    }
  }

  shouldComponentUpdate(nextProps) {
    return shouldContainerUpdate(this.props, nextProps)
  }

  componentWillUnmount() {
    const { dispatch, isLoggedIn, post } = this.props
    // this prevents the lover/reposters from firing since logout clears the json store
    if (!isLoggedIn) { return }
    if (!this.lovesWasOpen) {
      dispatch(toggleLovers(post, false))
    }
    if (!this.repostsWasOpen) {
      dispatch(toggleReposters(post, false))
    }
  }

  render() {
    const { author, paramsToken, post, streamError, streamType } = this.props
    if (streamType === ACTION_TYPES.POST.DETAIL_FAILURE && streamError && !post) {
      return (
        <PostDetailError>
          <ErrorState4xx />
        </PostDetailError>
      )
    }
    const props = {
      author,
      hasEditor: author && author.hasCommentingEnabled && !(post.isReposting || post.isEditing),
      key: `postDetail_${paramsToken}`,
      post,
      streamAction: author && author.hasCommentingEnabled ? loadComments(post, false) : null,
    }
    return <PostDetail {...props} />
  }
}

export default connect(mapStateToProps)(PostDetailContainer)

<|endoftext|>


<commit_before>// RDF constants
const RDF_SYNTAX = '<http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const FLOW_VOCAB = '<http://schema.jillix.net/vocab/';
const SCHEMA = '<http://schema.org/';

/* ADAPTER CAYLEY QUERIES */

// get entrypoint for adapter
exports.adapter = (g, entrypoint_name) => {
    return [

        // get entrypoint vars
        g.V(entrypoint_name).In().In()
        .Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Entrypoint>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'environment>', 'predicate')
        .Out(FLOW_VOCAB + 'json>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get sequence
        g.V(entrypoint_name).In().In().Tag('subject')
        .Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Entrypoint>')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All()
    ];
};

// reads sequence informations for flow
exports.flow = (g, sequence_id, role) => {
    return [

        // sequence details
        g.V(sequence_id)
        .Tag('subject')
        .Has(FLOW_VOCAB + 'role>', role)
        .Out([
            FLOW_VOCAB + 'role>',
            FLOW_VOCAB + 'onError>',
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'next>',
        ], 'predicate')
        .All(),

        // sequence handler details
        g.V(sequence_id)
        .Has(FLOW_VOCAB + 'role>', role)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out([
            RDF_SYNTAX + 'type>',
            FLOW_VOCAB + 'state>',
            FLOW_VOCAB + 'fn>',
            FLOW_VOCAB + 'sequence>',
            FLOW_VOCAB + 'next>'
        ], 'predicate')
        .All(),

        // sequence handler args
        g.V(sequence_id)
        .Has(FLOW_VOCAB + 'role>', role)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'args>', 'predicate')
        .Out(FLOW_VOCAB + 'json>')
        .Out(RDF_SYNTAX + 'string>')
        .All()
    ];
};

/* GET NODE QUERIES */
exports.get = (g, id, type, role) => {

    console.log('Flow-API.get:', id, type);
    return g.V(id)
    .Tag('subject')
    .Out([
        SCHEMA + 'name>',
        FLOW_VOCAB + 'json>'
    ], 'predicate')
    .Out(RDF_SYNTAX + 'string>')
    .All();
};

/* VISUALIZATION QUERIES */

// get network nodes with name
exports.vis_networks = (g, user_id) => {
    return g.V().Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Network>')
    .Tag('subject')
    .Out(SCHEMA + 'name>')
    .Save(RDF_SYNTAX + 'type>', 'predicate')
    .Out(RDF_SYNTAX + 'string>')
    .All();
};

// get all entrypoints of a network
exports.vis_entrypoints = (g, network_id) => {
    return [

        // get entrypoint nodes
        g.V(network_id)
        .Out(FLOW_VOCAB + 'entrypoint>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get entrypoint edges
        g.V(network_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'entrypoint>', 'predicate')
        .All()
    ]
};

// get details of an entrypoint
exports.vis_entrypoint = (g, entrypoint_id) => {
    return [

        // get environment nodes
        g.V(entrypoint_id)
        .Out(FLOW_VOCAB + 'environment>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get environment edge
        g.V(entrypoint_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'environment>', 'predicate')
        .All(),

        // get sequence nodes
        g.V(entrypoint_id)
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get sequence edge
        g.V(entrypoint_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All()
    ]
};

// get details of a sequence inclusive handlers
exports.vis_sequence = (g, sequence_id) => {
    return [
        // get end/err sequences
        g.V(sequence_id)
        .Out([
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'onError>'
        ])
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get end/error/next edges
        g.V(sequence_id)
        .Tag('subject')
        .Out([
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'onError>',
            FLOW_VOCAB + 'next>'
        ], 'predicate')
        .All(),

        // handler node
        g.V(sequence_id)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // handler edges
        g.V(sequence_id)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'next>', 'predicate')
        .All()
    ];
};

// get details of a handler
exports.vis_handler = (g, handler_id) => {
    return [

        // state node
        g.V(handler_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'state>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // arguments node
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'args>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

         // handler edges
        g.V(handler_id)
        .Tag('subject')
        .Out([
            FLOW_VOCAB + 'args>',
            FLOW_VOCAB + 'fn>',
            FLOW_VOCAB + 'sequence>'
        ], 'predicate')
        .All(),

        // argument's emits edges
        g.V(handler_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'args>')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All(),

        // sequences
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'args>')
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // emit sequence
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All()
    ];
};
<commit_msg>update queries<commit_after>// RDF constants
const RDF_SYNTAX = '<http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const FLOW_VOCAB = '<http://schema.jillix.net/vocab/';
const SCHEMA = '<http://schema.org/';

/* ADAPTER CAYLEY QUERIES */

// get entrypoint for adapter
exports.adapter = (g, entrypoint_name) => {
    return [

        // get entrypoint vars
        g.V(entrypoint_name).In().In()
        .Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Entrypoint>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'environment>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get sequence
        g.V(entrypoint_name).In().In().Tag('subject')
        .Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Entrypoint>')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All()
    ];
};

// reads sequence informations for flow
exports.flow = (g, sequence_id, role) => {
    return [

        // sequence details
        g.V(sequence_id)
        .Tag('subject')
        .Has(FLOW_VOCAB + 'role>', role)
        .Out([
            FLOW_VOCAB + 'role>',
            FLOW_VOCAB + 'onError>',
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'next>',
        ], 'predicate')
        .All(),

        // sequence handler details
        g.V(sequence_id)
        .Has(FLOW_VOCAB + 'role>', role)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out([
            RDF_SYNTAX + 'type>',
            FLOW_VOCAB + 'state>',
            FLOW_VOCAB + 'fn>',
            FLOW_VOCAB + 'sequence>',
            FLOW_VOCAB + 'next>'
        ], 'predicate')
        .All(),

        // sequence handler args
        g.V(sequence_id)
        .Has(FLOW_VOCAB + 'role>', role)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'args>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All()
    ];
};

/* GET NODE QUERIES */
exports.get = (g, id, type, role) => {

    console.log('Flow-API.get:', id, type);
    return g.V(id)
    .Tag('subject')
    .Out([
        SCHEMA + 'name>',
        FLOW_VOCAB + 'json>',
        FLOW_VOCAB + 'state>',
        FLOW_VOCAB + 'fn>'
    ], 'predicate')
    .Out(RDF_SYNTAX + 'string>')
    .All();
};

/* VISUALIZATION QUERIES */

// get network nodes with name
exports.vis_networks = (g, user_id) => {
    return g.V().Has(RDF_SYNTAX + 'type>', FLOW_VOCAB + 'Network>')
    .Tag('subject')
    .Out(SCHEMA + 'name>')
    .Save(RDF_SYNTAX + 'type>', 'predicate')
    .Out(RDF_SYNTAX + 'string>')
    .All();
};

// get all entrypoints of a network
exports.vis_entrypoints = (g, network_id) => {
    return [

        // get entrypoint nodes
        g.V(network_id)
        .Out(FLOW_VOCAB + 'entrypoint>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get entrypoint edges
        g.V(network_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'entrypoint>', 'predicate')
        .All()
    ]
};

// get details of an entrypoint
exports.vis_entrypoint = (g, entrypoint_id) => {
    return [

        // get environment nodes
        g.V(entrypoint_id)
        .Out(FLOW_VOCAB + 'environment>')
        .Tag('subject')
        .Out(SCHEMA + 'name>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get environment edge
        g.V(entrypoint_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'environment>', 'predicate')
        .All(),

        // get sequence nodes
        g.V(entrypoint_id)
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get sequence edge
        g.V(entrypoint_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All()
    ]
};

// get details of a sequence inclusive handlers
exports.vis_sequence = (g, sequence_id) => {
    return [
        // get end/err sequences
        g.V(sequence_id)
        .Out([
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'onError>'
        ])
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // get end/error/next edges
        g.V(sequence_id)
        .Tag('subject')
        .Out([
            FLOW_VOCAB + 'onEnd>',
            FLOW_VOCAB + 'onError>',
            FLOW_VOCAB + 'next>'
        ], 'predicate')
        .All(),

        // handler node
        g.V(sequence_id)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // handler edges
        g.V(sequence_id)
        .Out(FLOW_VOCAB + 'handler>')
        .Tag('subject')
        .Out(FLOW_VOCAB + 'next>', 'predicate')
        .All()
    ];
};

// get details of a handler
exports.vis_handler = (g, handler_id) => {
    return [

        // state node
        g.V(handler_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'state>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // arguments node
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'args>')
        .Tag('subject')
        .Out(SCHEMA + 'name>', 'predicate')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

         // handler edges
        g.V(handler_id)
        .Tag('subject')
        .Out([
            FLOW_VOCAB + 'args>',
            FLOW_VOCAB + 'fn>',
            FLOW_VOCAB + 'sequence>'
        ], 'predicate')
        .All(),

        // argument's emits edges
        g.V(handler_id)
        .Tag('subject')
        .Out(FLOW_VOCAB + 'args>')
        .Out(FLOW_VOCAB + 'sequence>', 'predicate')
        .All(),

        // sequences
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'args>')
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All(),

        // emit sequence
        g.V(handler_id)
        .Out(FLOW_VOCAB + 'sequence>')
        .Tag('subject')
        .Save(RDF_SYNTAX + 'type>', 'predicate')
        .Out(SCHEMA + 'name>')
        .Out(RDF_SYNTAX + 'string>')
        .All()
    ];
};
<|endoftext|>


<commit_before>/* jshint -W004 */

var fs = require("fs"),
    options = require('./options.js');

require('./commandline.js')(options);
require('./../node_modules/date-utils');

var mongoose = require("./schema/index.js")(options),
    queue = require("./queue.js")(options),
    saxStream = require("./../node_modules/sax").createStream(options.strict, options);

var Node = mongoose.model('node');
var Way = mongoose.model('way');
var Relation = mongoose.model('relation');
var entry;
var eof = false;

// Accounting

var readNodes = 0;
var readWays = 0;
var readRelations = 0;
var lastReadNodes = 0;
var lastReadWays = 0;
var lastReadRelations = 0;
var lastSavedNodes = 0;
var lastSavedWays = 0;
var lastSavedRelations = 0;

// TODO: break logging, timing and finalEntry in to seperate logging file.
function log() {
  var time = options.logInterval;
  var savedNode =  queue.input.node || 0;
  var queuedNode = queue.output.node || 0;
  var savedWay =  queue.input.way || 0;
  var queuedWay = queue.output.way || 0;
  var queuedRelation = queue.output.relation || 0;
  var savedRelation = queue.input.relation || 0;

  var nodeReadSpeed  = Math.round((readNodes - lastReadNodes) / time); // from read to theQ
  var nodeWriteSpeed = Math.round((savedNode - lastSavedNodes) / time); // from read to saved in mongo
  var wayReadSpeed   = Math.round((readWays - lastReadWays) / time);
  var wayWriteSpeed  = Math.round((savedWay - lastSavedWays) / time);
  var realtionWriteSpeed  = Math.round((savedRelation - lastSavedRelations) / time);
  var relationReadSpeed  = Math.round((readRelations - lastReadRelations) / time);

  console.log("nodes: "  + savedNode + "/" + queuedNode + "/" + readNodes + " read speed: " + nodeReadSpeed + "/s write speed: " + nodeWriteSpeed + "/s");
  console.log("ways: " + savedWay + "/" + queuedWay + "/" + readWays + " read speed: " + wayReadSpeed + "/s write speed: " + wayWriteSpeed + "/s");
  console.log("relations: " + savedRelation + "/" + queuedRelation + "/" + readRelations + " read speed: " + relationReadSpeed + "/s write speed: " + realtionWriteSpeed + "/s");

  lastSavedNodes = savedNode;
  lastSavedWays = savedWay;
  lastSavedRelations = savedRelation;
  lastReadNodes = readNodes;
  lastReadWays = readWays;
  lastReadRelations = readRelations;
}

// TODO: evented call back from queue.js;
var startTime = new Date();
function timing() {
  var endTime = new Date();

  var hours = startTime.getHoursBetween(endTime);
  var minutes = startTime.getMinutesBetween(endTime) - (hours * 60);
  var seconds = startTime.getSecondsBetween(endTime) - (minutes * 60);

  process.stdout.write("Total Time: ");
  process.stdout.write(hours + " H ");
  process.stdout.write(minutes + "M ");
  process.stdout.write(seconds + "S");
  process.stdout.write("\n");
}

// TODO: evented call back from queue.js with a context of final node type.
//
function isFinalEntry () {
  log();
  if (eof && !!!queue.node.length() && !!!queue.way.length()  && !!!queue.relation.length()) {
    timing();
    clearInterval(intervalID);
    mongoose.connection.close();
  }
}

var intervalID;
mongoose.connection.on('open', function () {

  console.log("Starting to process the nodes");
  console.log("Logging Legend: Successful Save / Queue Called / Read From Stream");

  intervalID = setInterval(isFinalEntry, options.logInterval * 1000);

  saxStream.on("opentag", parse);
  saxStream.on("closetag", closetag);

  if (options.filename) {
    fs.createReadStream(options.filename)
      .pipe(saxStream);
  } else {
    process.stdin.resume();
    process.stdin.setEncoding('utf8');
    process.stdin.pipe(saxStream);
  }

  saxStream.on("end", function() {
    eof = true;
    timing();
  });

  saxStream.on("error", function (e) {
    console.error("error!", e);
    this._parser.error = null;
    this._parser.resume();
  });
});

function parse (xmlNode)  {
  switch(xmlNode.name)
  {
    case "node":
      readNodes++;
      entry = new Node();
      var lat = parseFloat( xmlNode.attributes.lat.value );
      var lng = parseFloat( xmlNode.attributes.lon.value );
      entry.set("loc.coordinates", [lng,lat]);
      prepBaseNode(xmlNode);
      break;

    case "tag":
      var key   = "tags." + xmlNode.attributes.k.value.replace(/:/, "."),
          value = xmlNode.attributes.v.value;
      entry.set(key, value);
      break;

    case "nd":
      entry.nodes.push(parseInt(xmlNode.attributes.ref.value, 10));
      break;

    case "way":
      readWays++;
      entry = new Way();
      prepBaseNode(xmlNode);
      break;

    case "member":
      var member = {};
      for (var attribute in xmlNode.attributes) {
        var elm = xmlNode.attributes[attribute];
        if (attribute === "ref") elm.value = parseInt(elm.value, 10);
        member[attribute] = elm.value;
      }
      entry.members.push(member);
      break;

    case "relation":
      readRelations++;
      entry = new Relation();
      entry.members = [];
      prepBaseNode(xmlNode);
      break;

    case "osm":
      var val = {};
      for (var attribute in xmlNode.attributes) {
        val[attribute] = xmlNode.attributes[attribute].value;
      }
      break;

    case "bounds":
      var val = {};
      for (var attribute in xmlNode.attributes) {
        val[attribute] = xmlNode.attributes[attribute].value;
      }
      break;

    default:
      console.log(xmlNode);
      break;
  }
}

function closetag (tagName) {
  switch(tagName)
  {
    case "node":
      queue.node.push(entry);
      break;

    case "way":
      queue.way.push(entry);
      if (!!!queue.way.concurrency && !!!queue.node.length()) {
        console.log("Starting to process the ways");
        queue.way.concurrency = 300;
        queue.way.process();
      }
      break;

    case "relation":
      queue.relation.push(entry);
      if (!!!queue.relation.concurrency && !!!queue.way.length()) {
        console.log("Starting to process the relaitons");
        queue.relation.concurrency = 200;
        queue.relation.process();
      }
      break;
  }
}

function prepBaseNode (xmlNode) {
  entry.set("osm_id",  xmlNode.attributes.id.value);
  entry.set("type",  xmlNode.name);
  for (var attribute in xmlNode.attributes) {
    if (attribute === "id" || attribute === "lat" || attribute === "lon") continue;
    entry.set(attribute, xmlNode.attributes[attribute].value);
  }
}

<commit_msg>changed importer to keep default tag values, where namespaces are in use<commit_after>/* jshint -W004 */

var fs = require("fs"),
    options = require('./options.js');

require('./commandline.js')(options);
require('./../node_modules/date-utils');

var mongoose = require("./schema/index.js")(options),
    queue = require("./queue.js")(options),
    saxStream = require("./../node_modules/sax").createStream(options.strict, options);

var Node = mongoose.model('node');
var Way = mongoose.model('way');
var Relation = mongoose.model('relation');
var entry;
var eof = false;

// Accounting

var readNodes = 0;
var readWays = 0;
var readRelations = 0;
var lastReadNodes = 0;
var lastReadWays = 0;
var lastReadRelations = 0;
var lastSavedNodes = 0;
var lastSavedWays = 0;
var lastSavedRelations = 0;

// TODO: break logging, timing and finalEntry in to seperate logging file.
function log() {
  var time = options.logInterval;
  var savedNode =  queue.input.node || 0;
  var queuedNode = queue.output.node || 0;
  var savedWay =  queue.input.way || 0;
  var queuedWay = queue.output.way || 0;
  var queuedRelation = queue.output.relation || 0;
  var savedRelation = queue.input.relation || 0;

  var nodeReadSpeed  = Math.round((readNodes - lastReadNodes) / time); // from read to theQ
  var nodeWriteSpeed = Math.round((savedNode - lastSavedNodes) / time); // from read to saved in mongo
  var wayReadSpeed   = Math.round((readWays - lastReadWays) / time);
  var wayWriteSpeed  = Math.round((savedWay - lastSavedWays) / time);
  var realtionWriteSpeed  = Math.round((savedRelation - lastSavedRelations) / time);
  var relationReadSpeed  = Math.round((readRelations - lastReadRelations) / time);

  console.log("nodes: "  + savedNode + "/" + queuedNode + "/" + readNodes + " read speed: " + nodeReadSpeed + "/s write speed: " + nodeWriteSpeed + "/s");
  console.log("ways: " + savedWay + "/" + queuedWay + "/" + readWays + " read speed: " + wayReadSpeed + "/s write speed: " + wayWriteSpeed + "/s");
  console.log("relations: " + savedRelation + "/" + queuedRelation + "/" + readRelations + " read speed: " + relationReadSpeed + "/s write speed: " + realtionWriteSpeed + "/s");

  lastSavedNodes = savedNode;
  lastSavedWays = savedWay;
  lastSavedRelations = savedRelation;
  lastReadNodes = readNodes;
  lastReadWays = readWays;
  lastReadRelations = readRelations;
}

// TODO: evented call back from queue.js;
var startTime = new Date();
function timing() {
  var endTime = new Date();

  var hours = startTime.getHoursBetween(endTime);
  var minutes = startTime.getMinutesBetween(endTime) - (hours * 60);
  var seconds = startTime.getSecondsBetween(endTime) - (minutes * 60);

  process.stdout.write("Total Time: ");
  process.stdout.write(hours + " H ");
  process.stdout.write(minutes + "M ");
  process.stdout.write(seconds + "S");
  process.stdout.write("\n");
}

// TODO: evented call back from queue.js with a context of final node type.
//
function isFinalEntry () {
  log();
  if (eof && !!!queue.node.length() && !!!queue.way.length()  && !!!queue.relation.length()) {
    timing();
    clearInterval(intervalID);
    mongoose.connection.close();
  }
}

var intervalID;
mongoose.connection.on('open', function () {

  console.log("Starting to process the nodes");
  console.log("Logging Legend: Successful Save / Queue Called / Read From Stream");

  intervalID = setInterval(isFinalEntry, options.logInterval * 1000);

  saxStream.on("opentag", parse);
  saxStream.on("closetag", closetag);

  if (options.filename) {
    fs.createReadStream(options.filename)
      .pipe(saxStream);
  } else {
    process.stdin.resume();
    process.stdin.setEncoding('utf8');
    process.stdin.pipe(saxStream);
  }

  saxStream.on("end", function() {
    eof = true;
    timing();
  });

  saxStream.on("error", function (e) {
    console.error("error!", e);
    this._parser.error = null;
    this._parser.resume();
  });
});

function parse (xmlNode)  {
  switch(xmlNode.name)
  {
    case "node":
      readNodes++;
      entry = new Node();
      var lat = parseFloat( xmlNode.attributes.lat.value );
      var lng = parseFloat( xmlNode.attributes.lon.value );
      entry.set("loc.coordinates", [lng,lat]);
      prepBaseNode(xmlNode);
      break;

    case "tag":
      var keyRaw = xmlNode.attributes.k.value;

      if (stringContainsSubstring(keyRaw, ':') ) {
        var key = "tags." + keyRaw.replace(/:/, ".");
      }else{
        var key = "tags." + keyRaw + "." + keyRaw;
      }

      var value = xmlNode.attributes.v.value;
      entry.set(key, value);
      break;

    case "nd":
      entry.nodes.push(parseInt(xmlNode.attributes.ref.value, 10));
      break;

    case "way":
      readWays++;
      entry = new Way();
      prepBaseNode(xmlNode);
      break;

    case "member":
      var member = {};
      for (var attribute in xmlNode.attributes) {
        var elm = xmlNode.attributes[attribute];
        if (attribute === "ref") elm.value = parseInt(elm.value, 10);
        member[attribute] = elm.value;
      }
      entry.members.push(member);
      break;

    case "relation":
      readRelations++;
      entry = new Relation();
      entry.members = [];
      prepBaseNode(xmlNode);
      break;

    case "osm":
      var val = {};
      for (var attribute in xmlNode.attributes) {
        val[attribute] = xmlNode.attributes[attribute].value;
      }
      break;

    case "bounds":
      var val = {};
      for (var attribute in xmlNode.attributes) {
        val[attribute] = xmlNode.attributes[attribute].value;
      }
      break;

    default:
      console.log(xmlNode);
      break;
  }
}

function closetag (tagName) {
  switch(tagName)
  {
    case "node":
      queue.node.push(entry);
      break;

    case "way":
      queue.way.push(entry);
      if (!!!queue.way.concurrency && !!!queue.node.length()) {
        console.log("Starting to process the ways");
        queue.way.concurrency = 300;
        queue.way.process();
      }
      break;

    case "relation":
      queue.relation.push(entry);
      if (!!!queue.relation.concurrency && !!!queue.way.length()) {
        console.log("Starting to process the relaitons");
        queue.relation.concurrency = 200;
        queue.relation.process();
      }
      break;
  }
}

function prepBaseNode (xmlNode) {
  entry.set("osm_id",  xmlNode.attributes.id.value);
  entry.set("type",  xmlNode.name);
  for (var attribute in xmlNode.attributes) {
    if (attribute === "id" || attribute === "lat" || attribute === "lon") continue;
    entry.set(attribute, xmlNode.attributes[attribute].value);
  }
}

function stringContainsSubstring(str, substr){
  if(str.indexOf(substr) == -1) {
    return false;
  }else{
    return true;
  }
}

<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

"use strict";

var EXPORTED_SYMBOLS = [ "Preferences" ];

var Preferences = {
	branch : null,
	changeCallbacks : {},
	defaultPreferences : null,
	getFunctions : {},
	preferences : null,

	destroy : function() {
		this.preferences.removeObserver("", this);

		this.changeCallbacks = null;
		this.defaultPreferences = null;
		this.preferences = null;
		this.getFunctions = null;
	},

	init : function(branch) {
		this.branch = branch;

		this.changeCallbacks = {};
		this.defaultPreferences = {};
		this.preferences = {};
		this.getFunctions = {};

		this.defaultPreferences = Components.classes["@mozilla.org/preferences-service;1"].getService(
				Components.interfaces.nsIPrefService).getDefaultBranch(this.branch);
		this.preferences = Components.classes["@mozilla.org/preferences-service;1"].getService(
				Components.interfaces.nsIPrefService).getBranch(this.branch);
		this.preferences.QueryInterface(Components.interfaces.nsIPrefBranch2);
		this.preferences.addObserver("", this, false);
	},

	observe : function(subject, topic, data) {
		if (topic != "nsPref:changed") {
			return;
		}

		var changeCallback = this.changeCallbacks[data];

		if (changeCallback != null) {
			var value = this.getFunctions[data](data);
			changeCallback(data, value);
		}
	},

	register : function(name, defaultValue, onChange, defaultFunction, getFunction) {
		defaultFunction(name, defaultValue);

		this.changeCallbacks[name] = onChange;
		this.getFunctions[name] = getFunction;

		this.observe(null, "nsPref:changed", name);
	},

	registerBool : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setBoolPref, this.preferences.getBoolPref);
	},

	registerChar : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setCharPref, this.preferences.getCharPref);
	},

	registerInt : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setIntPref, this.preferences.getIntPref);
	}
};
<commit_msg>Added getInt and getBool functions.<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

"use strict";

var EXPORTED_SYMBOLS = [ "Preferences" ];

var Preferences = {
	branch : null,
	changeCallbacks : {},
	defaultPreferences : null,
	getFunctions : {},
	preferences : null,

	destroy : function() {
		this.preferences.removeObserver("", this);

		this.changeCallbacks = null;
		this.defaultPreferences = null;
		this.preferences = null;
		this.getFunctions = null;
	},

	getBool : function(name, defaultValue) {
		try {
			return this.preferences.getBoolPref(name);
		} catch (e) {
			// Empty on purpose
		}

		return defaultValue;
	},

	getInt : function(name, defaultValue) {
		try {
			return this.preferences.getIntPref(name);
		} catch (e) {
			// Empty on purpose
		}

		return defaultValue;
	},

	init : function(branch) {
		this.branch = branch;

		this.changeCallbacks = {};
		this.defaultPreferences = {};
		this.preferences = {};
		this.getFunctions = {};

		this.defaultPreferences = Components.classes["@mozilla.org/preferences-service;1"].getService(
				Components.interfaces.nsIPrefService).getDefaultBranch(this.branch);
		this.preferences = Components.classes["@mozilla.org/preferences-service;1"].getService(
				Components.interfaces.nsIPrefService).getBranch(this.branch);
		this.preferences.QueryInterface(Components.interfaces.nsIPrefBranch2);
		this.preferences.addObserver("", this, false);
	},

	observe : function(subject, topic, data) {
		if (topic != "nsPref:changed") {
			return;
		}

		var changeCallback = this.changeCallbacks[data];

		if (changeCallback != null) {
			var value = this.getFunctions[data](data);
			changeCallback(data, value);
		}
	},

	register : function(name, defaultValue, onChange, defaultFunction, getFunction) {
		defaultFunction(name, defaultValue);

		this.changeCallbacks[name] = onChange;
		this.getFunctions[name] = getFunction;

		this.observe(null, "nsPref:changed", name);
	},

	registerBool : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setBoolPref, this.preferences.getBoolPref);
	},

	registerChar : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setCharPref, this.preferences.getCharPref);
	},

	registerInt : function(name, defaultValue, onChange) {
		this.register(name, defaultValue, onChange, this.defaultPreferences.setIntPref, this.preferences.getIntPref);
	}
};
<|endoftext|>


<commit_before>import React, { PureComponent, PropTypes } from 'react';
import { BinaryChart } from 'binary-charts';
import { isMobile, nowAsEpoch } from 'binary-utils';
import { helpers } from 'binary-live-api';
import { chartApi, api as CoreApi } from '../_data/LiveData';
import { chartToDataType, getDataWithErrorHandling } from '../_chart-utils/Utils';

type Props = {
    contract: Contract,
    pipSize: number,
};

export default class ContractChart extends PureComponent {

    static contextTypes = {
        theme: PropTypes.oneOf(['light', 'dark']),
    };

    props: Props;

    constructor(props: Props) {
        super(props);
        this.state = {
            chartType: 'area',
            dataType: 'ticks',
            ticks: [],
            candles: [],
            noData: false,
        };
        this.api = chartApi(0);
        this.hasTick = true;
        this.contractEnd = undefined;       // used to know when to unsubscribe
    }

    componentWillMount() {
        this.api.events.on('tick', data => {
            if (!this.hasTick) {
                this.api.events.ignoreAll('tick');
                const { contract } = this.props;
                throw new Error(`Not supposed to have tick stream! Contract: ${JSON.stringify(contract)}`);
            }

            this.ticksId = data.tick.id;            // problematic, sometimes it will both be ohlc stream, and screw u !!

            const old = this.state.ticks;
            const newTick = {
                epoch: +data.tick.epoch,
                quote: +data.tick.quote,
            };
            this.setState({ ticks: old.concat([newTick]) });

            // unsubscribe after contract ends
            if (this.contractEnd && newTick.epoch > this.contractEnd) {
                this.api.unsubscribeByID(data.tick.id);
            }
        });

        this.api.events.on('ohlc', data => {
            this.ohlcId = data.ohlc.id;

            const old = this.state.candles;
            // list of candles might be received later than candles stream due to size
            // do not process single candle that arrived before list of candles
            if (old.length < 3) {
                return;
            }

            const ohlc = data.ohlc;
            const newOHLC = {
                epoch: +(ohlc.open_time || ohlc.epoch),
                open: +ohlc.open,
                high: +ohlc.high,
                low: +ohlc.low,
                close: +ohlc.close,
            };
            const last1 = old[old.length - 1];
            const last2 = old[old.length - 2];
            const last3 = old[old.length - 3];
            const interval = last2.epoch - last3.epoch;
            const diff = newOHLC.epoch - last1.epoch;

            // new candles might belong to the same interval of last candle
            // replace instead of append in that case
            if (diff < interval) {
                const newOHLCArr = old.slice(0, -1);
                newOHLCArr.push(newOHLC);

                if (!this.hasTick) {
                    const newTicks = newOHLCArr.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                    this.setState({ ticks: newTicks, candles: newOHLCArr });
                } else {
                    this.setState({ candles: newOHLCArr });
                }
            } else {
                const newCandles = old.concat([newOHLC]);

                if (!this.hasTick) {
                    const newTicks = newCandles.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                    this.setState({ ticks: newTicks, candles: newCandles });
                } else {
                    this.setState({ candles: newCandles });
                }
            }

            // unsubscribe after contract ends
            if (this.contractEnd && newOHLC.epoch > this.contractEnd) {
                this.api.unsubscribeByID(data.ohlc.id);
            }
        });

        this.prepareDataForChart();
    }

    componentWillReceiveProps(nextProps) {
        const { contract } = nextProps;
        const { date_expiry, exit_tick_time } = contract;

        // for contract that was not ended when component mount
        // compute end time when it ended
        if (!this.contractEnd && (date_expiry || exit_tick_time)) {
            const { end } = helpers.computeStartEndForContract(contract);
            this.contractEnd = end;
        }
    }

    componentWillUnmount() {
        this.unsubscribe();
        this.api.events.ignoreAll('tick');
        this.api.events.ignoreAll('ohlc');
    }

    unsubscribe = () => {
        if (this.ticksId) this.api.unsubscribeByID(this.ticksId);
        if (this.ohlcId) this.api.unsubscribeByID(this.ohlcId);
    }

    updateData = (data, type) => {
        if (type === 'ticks') {
            this.setState({ ticks: data });
        } else {
            this.setState({ candles: data });
        }

        return data;
    }

    prepareDataForChart = () => {
        const { contract } = this.props;
        const toStream = !contract.sell_time;

        if (toStream && !contract.id) {
            CoreApi.subscribeToOpenContract(contract.contract_id);
        }

        const { start, end } = helpers.computeStartEndForContract(contract);

        // escape earlier if contract not started
        if (start > nowAsEpoch()) {
            this.setState({ noData: true });
            return;
        }

        if (contract.sell_time) {
            this.contractEnd = end;
        }

        const durationInSecs = end - start;

        // 1.5 hour = 90 minutes * 60 secs
        if (durationInSecs < 90 * 60) {
            this.hasTick = true;

            const getDataCall = (errCode) => {
                if (errCode === 'StreamingNotAllowed') {
                    this.setState({ noData: true });
                    return Promise.resolve();
                }

                return this.api
                    .getTickHistory(contract.underlying, {
                        start,
                        end,
                        count: 4999,
                        adjust_start_time: 1,
                        subscribe: toStream && !errCode ? 1 : undefined,
                    });
            };

            getDataWithErrorHandling(getDataCall).then(r => {
                if (!r) return;

                const ticks = r.history.times.map((t, idx) => {
                    const quote = r.history.prices[idx];
                    return { epoch: +t, quote: +quote };
                });
                this.updateData(ticks, 'ticks');
            });
        } else {
            this.hasTick = false;
        }

        const getDataCall = (errCode) => {
            if (errCode === 'StreamingNotAllowed') {
                this.setState({ noData: true });
                return Promise.resolve();
            }

            return this.api.autoAdjustGetData(contract.underlying, start, end, 'candles', toStream && !errCode);
        };

        getDataWithErrorHandling(getDataCall).then(r => {
            if (!r) return;

            this.updateData(r.candles, 'candles');

            if (!this.hasTick) {
                const ticksDerivedFromOHLC = r.candles.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                this.updateData(ticksDerivedFromOHLC, 'ticks');
            }
        });
    }

    changeChartType = (type: ChartType) => {
        const { chartType } = this.state;
        const { contract } = this.props;

        const allowCandle = !contract.tick_count;
        const newDataType = chartToDataType[type];

        if ((!allowCandle && newDataType === 'candles') || chartType === type) {
            return;
        }

        if (newDataType === this.state.dataType) {
            this.setState({ chartType: type });
            return;
        }

        this.setState({ chartType: type, dataType: newDataType });
    }

    render() {
        const { contract, pipSize } = this.props;
        const { theme } = this.context;
        const { date_start, exit_tick_time, sell_spot_time } = contract;
        const { chartType, dataType, noData } = this.state;
        const data = this.state[dataType];
        const endTime = exit_tick_time || sell_spot_time;

        // handle edge case where contract ends before it starts, show No data available message on chart
        const hasNoData = (+date_start > +endTime) || noData;

        return (
            <BinaryChart
                className="contract-chart"
                compactToolbar
                hideTimeFrame
                showTooltips={!isMobile()}
                showAllTimeFrame={false}
                contract={contract}
                symbol={contract.underlying}
                assetName={contract.symbolName}
                ticks={hasNoData ? undefined : data}
                type={chartType}
                theme={theme}
                shiftMode="dynamic"
                noData={hasNoData}
                pipSize={pipSize}
                onTypeChange={!hasNoData ? this.changeChartType : undefined}
            />
        );
    }
}
<commit_msg>Disable ohlc chart type when contract is less than 5 minutes (#578)<commit_after>import React, { PureComponent, PropTypes } from 'react';
import { BinaryChart } from 'binary-charts';
import { isMobile, nowAsEpoch } from 'binary-utils';
import { helpers } from 'binary-live-api';
import { chartApi, api as CoreApi } from '../_data/LiveData';
import { chartToDataType, getDataWithErrorHandling } from '../_chart-utils/Utils';

type Props = {
    contract: Contract,
    pipSize: number,
};

export default class ContractChart extends PureComponent {

    static contextTypes = {
        theme: PropTypes.oneOf(['light', 'dark']),
    };

    props: Props;

    constructor(props: Props) {
        super(props);
        this.state = {
            chartType: 'area',
            dataType: 'ticks',
            ticks: [],
            candles: [],
            noData: false,
        };
        this.api = chartApi(0);
        this.hasTick = true;
        this.contractEnd = undefined;       // used to know when to unsubscribe
    }

    componentWillMount() {
        this.api.events.on('tick', data => {
            if (!this.hasTick) {
                this.api.events.ignoreAll('tick');
                const { contract } = this.props;
                throw new Error(`Not supposed to have tick stream! Contract: ${JSON.stringify(contract)}`);
            }

            this.ticksId = data.tick.id;            // problematic, sometimes it will both be ohlc stream, and screw u !!

            const old = this.state.ticks;
            const newTick = {
                epoch: +data.tick.epoch,
                quote: +data.tick.quote,
            };
            this.setState({ ticks: old.concat([newTick]) });

            // unsubscribe after contract ends
            if (this.contractEnd && newTick.epoch > this.contractEnd) {
                this.api.unsubscribeByID(data.tick.id);
            }
        });

        this.api.events.on('ohlc', data => {
            this.ohlcId = data.ohlc.id;

            const old = this.state.candles;
            // list of candles might be received later than candles stream due to size
            // do not process single candle that arrived before list of candles
            if (old.length < 3) {
                return;
            }

            const ohlc = data.ohlc;
            const newOHLC = {
                epoch: +(ohlc.open_time || ohlc.epoch),
                open: +ohlc.open,
                high: +ohlc.high,
                low: +ohlc.low,
                close: +ohlc.close,
            };
            const last1 = old[old.length - 1];
            const last2 = old[old.length - 2];
            const last3 = old[old.length - 3];
            const interval = last2.epoch - last3.epoch;
            const diff = newOHLC.epoch - last1.epoch;

            // new candles might belong to the same interval of last candle
            // replace instead of append in that case
            if (diff < interval) {
                const newOHLCArr = old.slice(0, -1);
                newOHLCArr.push(newOHLC);

                if (!this.hasTick) {
                    const newTicks = newOHLCArr.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                    this.setState({ ticks: newTicks, candles: newOHLCArr });
                } else {
                    this.setState({ candles: newOHLCArr });
                }
            } else {
                const newCandles = old.concat([newOHLC]);

                if (!this.hasTick) {
                    const newTicks = newCandles.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                    this.setState({ ticks: newTicks, candles: newCandles });
                } else {
                    this.setState({ candles: newCandles });
                }
            }

            // unsubscribe after contract ends
            if (this.contractEnd && newOHLC.epoch > this.contractEnd) {
                this.api.unsubscribeByID(data.ohlc.id);
            }
        });

        this.prepareDataForChart();
    }

    componentWillReceiveProps(nextProps) {
        const { contract } = nextProps;
        const { date_expiry, exit_tick_time } = contract;

        // for contract that was not ended when component mount
        // compute end time when it ended
        if (!this.contractEnd && (date_expiry || exit_tick_time)) {
            const { end } = helpers.computeStartEndForContract(contract);
            this.contractEnd = end;
        }
    }

    componentWillUnmount() {
        this.unsubscribe();
        this.api.events.ignoreAll('tick');
        this.api.events.ignoreAll('ohlc');
    }

    unsubscribe = () => {
        if (this.ticksId) this.api.unsubscribeByID(this.ticksId);
        if (this.ohlcId) this.api.unsubscribeByID(this.ohlcId);
    }

    updateData = (data, type) => {
        if (type === 'ticks') {
            this.setState({ ticks: data });
        } else {
            this.setState({ candles: data });
        }

        return data;
    }

    prepareDataForChart = () => {
        const { contract } = this.props;
        const toStream = !contract.sell_time;

        if (toStream && !contract.id) {
            CoreApi.subscribeToOpenContract(contract.contract_id);
        }

        const { start, end } = helpers.computeStartEndForContract(contract);

        // escape earlier if contract not started
        if (start > nowAsEpoch()) {
            this.setState({ noData: true });
            return;
        }

        if (contract.sell_time) {
            this.contractEnd = end;
        }

        const durationInSecs = end - start;

        // 1.5 hour = 90 minutes * 60 secs
        if (durationInSecs < 90 * 60) {
            this.hasTick = true;

            const getDataCall = (errCode) => {
                if (errCode === 'StreamingNotAllowed') {
                    this.setState({ noData: true });
                    return Promise.resolve();
                }

                return this.api
                    .getTickHistory(contract.underlying, {
                        start,
                        end,
                        count: 4999,
                        adjust_start_time: 1,
                        subscribe: toStream && !errCode ? 1 : undefined,
                    });
            };

            getDataWithErrorHandling(getDataCall).then(r => {
                if (!r) return;

                const ticks = r.history.times.map((t, idx) => {
                    const quote = r.history.prices[idx];
                    return { epoch: +t, quote: +quote };
                });
                this.updateData(ticks, 'ticks');
            });
        } else {
            this.hasTick = false;
        }

        const getDataCall = (errCode) => {
            if (errCode === 'StreamingNotAllowed') {
                this.setState({ noData: true });
                return Promise.resolve();
            }

            return this.api.autoAdjustGetData(contract.underlying, start, end, 'candles', toStream && !errCode);
        };

        getDataWithErrorHandling(getDataCall).then(r => {
            if (!r) return;

            this.updateData(r.candles, 'candles');

            // for long contract, dont fetch ticks to avoid multiple huge network call
            // use OHLC value to represent ticks data instead
            if (!this.hasTick) {
                const ticksDerivedFromOHLC = r.candles.map(c => ({ epoch: +c.epoch, quote: +c.close }));
                this.updateData(ticksDerivedFromOHLC, 'ticks');
            }
        });
    }

    changeChartType = (type: ChartType) => {
        const { chartType } = this.state;
        const { contract } = this.props;

        const { date_start, date_expiry } = contract;

        // no candles for contract less than 5 minutes
        // tick_count is checked too, because date_expiry is not available in tick trade contract
        const allowCandle = !contract.tick_count && (date_expiry - date_start) > 300;
        const newDataType = chartToDataType[type];

        if ((!allowCandle && newDataType === 'candles') || chartType === type) {
            return;
        }

        if (newDataType === this.state.dataType) {
            this.setState({ chartType: type });
            return;
        }

        this.setState({ chartType: type, dataType: newDataType });
    }

    render() {
        const { contract, pipSize } = this.props;
        const { theme } = this.context;
        const { date_start, date_expiry, exit_tick_time, sell_spot_time, tick_count } = contract;
        const { chartType, dataType, noData } = this.state;
        const data = this.state[dataType];
        const endTime = exit_tick_time || sell_spot_time;

        // handle edge case where contract ends before it starts, show No data available message on chart
        const hasNoData = (+date_start > +endTime) || noData;
        const allowOHLC = !tick_count && (date_expiry - date_start) > 300;
        return (
            <BinaryChart
                allowOHLC={allowOHLC}
                className="contract-chart"
                compactToolbar
                hideTimeFrame
                showTooltips={!isMobile()}
                showAllTimeFrame={false}
                contract={contract}
                symbol={contract.underlying}
                assetName={contract.symbolName}
                ticks={hasNoData ? undefined : data}
                type={chartType}
                theme={theme}
                shiftMode="dynamic"
                noData={hasNoData}
                pipSize={pipSize}
                onTypeChange={!hasNoData ? this.changeChartType : undefined}
            />
        );
    }
}
<|endoftext|>


<commit_before>(function () {
function Rule(name, symbols, postprocess) {
    this.name = name;
    this.symbols = symbols;        // a list of literal | regex class | nonterminal
    this.postprocess = postprocess;
    return this;
}

Rule.prototype.toString = function(withCursorAt) {
    function stringifySymbolSequence (e) {
        return (e.literal) ? JSON.stringify(e.literal)
                           : e.toString();
    }
    var symbolSequence = (typeof withCursorAt === "undefined")
                         ? this.symbols.map(stringifySymbolSequence).join(' ')
                         : (   this.symbols.slice(0, withCursorAt).map(stringifySymbolSequence).join(' ')
                             + " ● "
                             + this.symbols.slice(withCursorAt).map(stringifySymbolSequence).join(' ')     );
    return this.name + " → " + symbolSequence;
}

// a State is a rule at a position from a given starting point in the input stream (reference)
function State(rule, expect, reference) {
    this.rule = rule;
    this.expect = expect;
    this.reference = reference;
    this.data = [];
}

State.prototype.toString = function() {
    return "{" + this.rule.toString(this.expect) + "}, from: " + (this.reference || 0);
};

State.prototype.nextState = function(data) {
    var state = new State(this.rule, this.expect + 1, this.reference);
    state.data = this.data.slice(0);  // make a cheap copy of currentState's data
    state.data.push(data);            // append the passed data
    return state;
};

State.prototype.consumeTerminal = function(inp) {
    var val = false;
    if (this.rule.symbols[this.expect]) {                  // is there a symbol to test?
       if (this.rule.symbols[this.expect].test) {          // is the symbol a regex?
          if (this.rule.symbols[this.expect].test(inp)) {  // does the regex match
             val = this.nextState(inp);  // nextState on a successful regex match
          }
       } else {   // not a regex, must be a literal
          if (this.rule.symbols[this.expect].literal === inp) {
             val = this.nextState(inp);  // nextState on a successful literal match
          }
       }
    }
    return val;
};

State.prototype.consumeNonTerminal = function(inp) {
    if (this.rule.symbols[this.expect] === inp) {
        return this.nextState(inp);
    }
    return false;
};

State.prototype.process = function(location, table, rules, addedRules) {
    if (this.expect === this.rule.symbols.length) {
        // I have completed a rule
        if (this.rule.postprocess) {
            this.data = this.rule.postprocess(this.data, this.reference, Parser.fail);
        }
        if (!(this.data === Parser.fail)) {
            var w = 0;
            // We need a while here because the empty rule will
            // modify table[reference]. (when location === reference)
            var s,x;
            while (w < table[this.reference].length) {
                s = table[this.reference][w];
                x = s.consumeNonTerminal(this.rule.name);
                if (x) {
                    x.data[x.data.length-1] = this.data;
                    table[location].push(x);
                }
                w++;
            }

            // Remove this rule from "addedRules" so that another one can be
            // added if some future added rule requires it.
            // Note: I can be optimized by someone clever and not-lazy. Somehow
            // queue rules so that everything that this completion "spawns" can
            // affect the rest of the rules yet-to-be-added-to-the-table.
            // Maybe.
            var i = addedRules.indexOf(this.rule);
            if (i !== -1) {
                addedRules.splice(i, 1);
            }
        }
    } else {
        // I'm not done, but I can predict something
        var exp = this.rule.symbols[this.expect];

        // for each rule
        var me = this;
        rules.forEach(function(r) {
            // if I expect it, and it hasn't been added already
            if (r.name === exp && addedRules.indexOf(r) === -1) {
                // Make a note that you've added it already, and don't need to
                // add it again; otherwise left recursive rules are going to go
                // into an infinite loop by adding themselves over and over
                // again.

                // If it's the null rule, however, you don't do this because it
                // affects the current table row, so you might need it to be
                // called again later. Instead, I just insert a copy whose
                // state has been advanced one position (since that's all the
                // null rule means anyway)

                if (r.symbols.length > 0) {
                    addedRules.push(r);
                    table[location].push(new State(r, 0, location));
                } else {
                    // Empty rule
                    // This is special
                    var copy = me.consumeNonTerminal(r.name);
                    if (r.postprocess) {
                        copy.data[copy.data.length-1] = r.postprocess([], this.reference);
                    } else {
                        copy.data[copy.data.length-1] = [];
                    }
                    table[location].push(copy);
                }
            }
        });
    }
};

function Parser(rules, start) {
    var table = this.table = [];
    this.rules = rules.map(function (r) { return (new Rule(r.name, r.symbols, r.postprocess)); });
    this.start = start = start || this.rules[0].name;
    // Setup a table
    var addedRules = [];
    this.table.push([]);
    // I could be expecting anything.
    this.rules.forEach(function (r) {
        if (r.name === start) {  // add all rules named start
            addedRules.push(r);
            table[0].push(new State(r, 0, 0));
        }});  // this should refer to this object, not each rule inside the forEach
    this.advanceTo(0, addedRules);
    this.current = 0;
}

// create a reserved token for indicating a parse fail
Parser.fail = {};

Parser.prototype.advanceTo = function(n, addedRules) {
    // Advance a table, take the closure of .process for location n in the input stream
    var w = 0;
    while (w < this.table[n].length) {
        (this.table[n][w]).process(n, this.table, this.rules, addedRules);
        w++;
    }
}

Parser.prototype.feed = function(chunk) {
    for (var chunkPos = 0; chunkPos < chunk.length; chunkPos++) {
        // We add new states to table[current+1]
        this.table.push([]);

        // Advance all tokens that expect the symbol
        // So for each state in the previous row,

        for (var w = 0; w < this.table[this.current + chunkPos].length; w++) {
            var s = this.table[this.current + chunkPos][w];
            var x = s.consumeTerminal(chunk[chunkPos]);      // Try to consume the token
            if (x) {
                // And then add it
                this.table[this.current + chunkPos + 1].push(x);
            }
        }

        // Next, for each of the rules, we either
        // (a) complete it, and try to see if the reference row expected that
        //     rule
        // (b) predict the next nonterminal it expects by adding that
        //     nonterminal's start state
        // To prevent duplication, we also keep track of rules we have already
        // added

        var addedRules = [];
        this.advanceTo(this.current + chunkPos + 1, addedRules);

        // If needed, throw an error:
        if (this.table[this.table.length-1].length === 0) {
            // No states at all! This is not good.
            var err = new Error(
                "nearley: No possible parsings (@" + (this.current + chunkPos)
                    + ": '" + chunk[chunkPos] + "')."
            );
            err.offset = this.current + chunkPos;
            throw err;
        }
    }

    this.current += chunkPos;
    // Incrementally keep track of results
    this.results = this.finish();

    // Allow chaining, for whatever it's worth
    return this;
};

Parser.prototype.finish = function() {
    // Return the possible parsings
    var considerations = [];
    var myself = this;
    this.table[this.table.length-1].forEach(function (t) {
        if (t.rule.name === myself.start
                && t.expect === t.rule.symbols.length
                && t.reference === 0
                && t.data !== Parser.fail) {
            considerations.push(t);
        }
    });
    return considerations.map(function(c) {return c.data; });
};

var nearley = {
    Parser: Parser,
    Rule: Rule
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
   module.exports = nearley;
} else {
   window.nearley = nearley;
}
})();
<commit_msg>hopefully squashed that bug for good<commit_after>(function () {
function Rule(name, symbols, postprocess) {
    this.name = name;
    this.symbols = symbols;        // a list of literal | regex class | nonterminal
    this.postprocess = postprocess;
    return this;
}

Rule.prototype.toString = function(withCursorAt) {
    function stringifySymbolSequence (e) {
        return (e.literal) ? JSON.stringify(e.literal)
                           : e.toString();
    }
    var symbolSequence = (typeof withCursorAt === "undefined")
                         ? this.symbols.map(stringifySymbolSequence).join(' ')
                         : (   this.symbols.slice(0, withCursorAt).map(stringifySymbolSequence).join(' ')
                             + " ● "
                             + this.symbols.slice(withCursorAt).map(stringifySymbolSequence).join(' ')     );
    return this.name + " → " + symbolSequence;
}

// a State is a rule at a position from a given starting point in the input stream (reference)
function State(rule, expect, reference) {
    this.rule = rule;
    this.expect = expect;
    this.reference = reference;
    this.data = [];
}

State.prototype.toString = function() {
    return "{" + this.rule.toString(this.expect) + "}, from: " + (this.reference || 0);
};

State.prototype.nextState = function(data) {
    var state = new State(this.rule, this.expect + 1, this.reference);
    state.data = this.data.slice(0);  // make a cheap copy of currentState's data
    state.data.push(data);            // append the passed data
    return state;
};

State.prototype.consumeTerminal = function(inp) {
    var val = false;
    if (this.rule.symbols[this.expect]) {                  // is there a symbol to test?
       if (this.rule.symbols[this.expect].test) {          // is the symbol a regex?
          if (this.rule.symbols[this.expect].test(inp)) {  // does the regex match
             val = this.nextState(inp);  // nextState on a successful regex match
          }
       } else {   // not a regex, must be a literal
          if (this.rule.symbols[this.expect].literal === inp) {
             val = this.nextState(inp);  // nextState on a successful literal match
          }
       }
    }
    return val;
};

State.prototype.consumeNonTerminal = function(inp) {
    if (this.rule.symbols[this.expect] === inp) {
        return this.nextState(inp);
    }
    return false;
};

State.prototype.process = function(location, table, rules, addedRules) {
    if (this.expect === this.rule.symbols.length) {
        // I have completed a rule
        if (this.rule.postprocess) {
            this.data = this.rule.postprocess(this.data, this.reference, Parser.fail);
        }
        if (!(this.data === Parser.fail)) {
            var w = 0;
            // We need a while here because the empty rule will
            // modify table[reference]. (when location === reference)
            var s,x;
            while (w < table[this.reference].length) {
                s = table[this.reference][w];
                x = s.consumeNonTerminal(this.rule.name);
                if (x) {
                    x.data[x.data.length-1] = this.data;
                    table[location].push(x);
                }
                w++;
            }

            // --- The comment below is OUTDATED. It's left so that future
            // editors know not to try and do that.

            // Remove this rule from "addedRules" so that another one can be
            // added if some future added rule requires it.
            // Note: I can be optimized by someone clever and not-lazy. Somehow
            // queue rules so that everything that this completion "spawns" can
            // affect the rest of the rules yet-to-be-added-to-the-table.
            // Maybe.

            // I repeat, this is a *bad* idea.

            // var i = addedRules.indexOf(this.rule);
            // if (i !== -1) {
            //     addedRules.splice(i, 1);
            // }
        }
    } else {
        // In case I missed an older nullable's sweep, update yourself. See
        // above context for why this makes sense.

        var ind = table[location].indexOf(this);
        for (var i=0; i<ind; i++) {
            var state = table[location][i];
            if (state.rule.symbols.length === state.expect && state.reference === location) {
                var x = this.consumeNonTerminal(state.rule.name);
                if (x) {
                    x.data[x.data.length-1] = state.data;
                    table[location].push(x);
                }
            }
        }

        // I'm not done, but I can predict something
        var exp = this.rule.symbols[this.expect];

        // for each rule
        var me = this;
        rules.forEach(function(r) {
            // if I expect it, and it hasn't been added already
            if (r.name === exp && addedRules.indexOf(r) === -1) {
                // Make a note that you've added it already, and don't need to
                // add it again; otherwise left recursive rules are going to go
                // into an infinite loop by adding themselves over and over
                // again.

                // If it's the null rule, however, you don't do this because it
                // affects the current table row, so you might need it to be
                // called again later. Instead, I just insert a copy whose
                // state has been advanced one position (since that's all the
                // null rule means anyway)

                if (r.symbols.length > 0) {
                    addedRules.push(r);
                    table[location].push(new State(r, 0, location));
                } else {
                    // Empty rule
                    // This is special
                    var copy = me.consumeNonTerminal(r.name);
                    if (r.postprocess) {
                        copy.data[copy.data.length-1] = r.postprocess([], this.reference);
                    } else {
                        copy.data[copy.data.length-1] = [];
                    }
                    table[location].push(copy);
                }
            }
        });
    }
};

function Parser(rules, start) {
    var table = this.table = [];
    this.rules = rules.map(function (r) { return (new Rule(r.name, r.symbols, r.postprocess)); });
    this.start = start = start || this.rules[0].name;
    // Setup a table
    var addedRules = [];
    this.table.push([]);
    // I could be expecting anything.
    this.rules.forEach(function (r) {
        if (r.name === start) {  // add all rules named start
            addedRules.push(r);
            table[0].push(new State(r, 0, 0));
        }});  // this should refer to this object, not each rule inside the forEach
    this.advanceTo(0, addedRules);
    this.current = 0;
}

// create a reserved token for indicating a parse fail
Parser.fail = {};

Parser.prototype.advanceTo = function(n, addedRules) {
    // Advance a table, take the closure of .process for location n in the input stream
    var w = 0;
    while (w < this.table[n].length) {
        (this.table[n][w]).process(n, this.table, this.rules, addedRules);
        w++;
    }
}

Parser.prototype.feed = function(chunk) {
    for (var chunkPos = 0; chunkPos < chunk.length; chunkPos++) {
        // We add new states to table[current+1]
        this.table.push([]);

        // Advance all tokens that expect the symbol
        // So for each state in the previous row,

        for (var w = 0; w < this.table[this.current + chunkPos].length; w++) {
            var s = this.table[this.current + chunkPos][w];
            var x = s.consumeTerminal(chunk[chunkPos]);      // Try to consume the token
            if (x) {
                // And then add it
                this.table[this.current + chunkPos + 1].push(x);
            }
        }

        // Next, for each of the rules, we either
        // (a) complete it, and try to see if the reference row expected that
        //     rule
        // (b) predict the next nonterminal it expects by adding that
        //     nonterminal's start state
        // To prevent duplication, we also keep track of rules we have already
        // added

        var addedRules = [];
        this.advanceTo(this.current + chunkPos + 1, addedRules);

        // If needed, throw an error:
        if (this.table[this.table.length-1].length === 0) {
            // No states at all! This is not good.
            var err = new Error(
                "nearley: No possible parsings (@" + (this.current + chunkPos)
                    + ": '" + chunk[chunkPos] + "')."
            );
            err.offset = this.current + chunkPos;
            throw err;
        }
    }

    this.current += chunkPos;
    // Incrementally keep track of results
    this.results = this.finish();

    // Allow chaining, for whatever it's worth
    return this;
};

Parser.prototype.finish = function() {
    // Return the possible parsings
    var considerations = [];
    var myself = this;
    this.table[this.table.length-1].forEach(function (t) {
        if (t.rule.name === myself.start
                && t.expect === t.rule.symbols.length
                && t.reference === 0
                && t.data !== Parser.fail) {
            considerations.push(t);
        }
    });
    return considerations.map(function(c) {return c.data; });
};

var nearley = {
    Parser: Parser,
    Rule: Rule
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
   module.exports = nearley;
} else {
   window.nearley = nearley;
}
})();
<|endoftext|>


<commit_before>const isNewPlayer = () => !!document.querySelector('.mz-player-control');

const config = [
  {
    test: () => !isNewPlayer(),
    supports: {
      playpause: true,
      previous: true,
      next: true
    },
    playStateSelector: '.player-control',
    playStateClass: 'pause-state',
    playPauseSelector: '.player-control',
    titleSelector: '.player-cloudcast-title',
    artistSelector: '.player-cloudcast-author-link',
    artworkImageSelector: '.player-cloudcast-image img'
  },
  {
    test: () => isNewPlayer(),
    supports: {
      playpause: true,
      previous: true,
      next: true
    },
    playStateSelector: '.mz-player-control',
    playStateClass: 'mz-pause-state',
    playPauseSelector: '.mz-player-control',
    titleSelector: '.mz-player-cloudcast-title',
    artistSelector: '.mz-player-cloudcast-author-link',
    artworkImageSelector: '.mz-player-cloudcast-image img'
  }
];

controller = new BasicController(config);

controller.override('getAlbumArt', function(_super) {
  let art = _super();
  return art && art.replace(/\/60\//g, '\/300\/')
                   .replace(/\/60x60\//g, '\/300x300\/');
});

const CUSTOM_EVENT_TYPE = 'mxswayEvent';
function mxTriggerEvent(type) {
  const event = new CustomEvent(CUSTOM_EVENT_TYPE, { detail: type });
  document.dispatchEvent(event);
}

controller.override('nextSong', function() {
  mxTriggerEvent('next');
});

controller.override('previousSong', function() {
  mxTriggerEvent('prev');
});

const scrubbingCode = `
(function() {
  const SCRUBBER_SELECTOR_OLD = '.player-scrubber';
  const SCRUBBER_SELECTOR_NEW = '.mz-player-scrubber';
  const SKIP_TIME = 60; // 1 minute

  const getScrubberScope = (function() {
    let scope;

    return function() {
      if (!scope) {
        let $scrubber = $(SCRUBBER_SELECTOR_OLD);
        $scrubber = ($scrubber.length > 0) ? $scrubber : $(SCRUBBER_SELECTOR_NEW);
        scope = $scrubber.scope();
      }

      return scope;
    };
  })();

  function scrub(type) {
    const delta = type === 'next' ? SKIP_TIME : -SKIP_TIME;
    moveScrubber(delta);
  }

  function getNewPosition(delta) {
    const { audioPosition, audioLength } = getScrubberScope().player;

    // setup new time, and check for overflow
    let position = audioPosition + delta;

    if (position > audioLength) {
      position = audioLength;
    } else if (position < 0) {
      position = 0;
    }

    return position;
  }

  function moveScrubber(delta) {
    getScrubberScope().$emit('slider:stop', getNewPosition(delta));
  }

  document.addEventListener('${CUSTOM_EVENT_TYPE}', function ({ detail: type }) {
    scrub(type);
  });
}());
`;

controller.runInPage(scrubbingCode);
<commit_msg>Use "positive" test functions in config (#108)<commit_after>const isOldPlayer = () => !!document.querySelector('.player-control');
const isNewPlayer = () => !!document.querySelector('.mz-player-control');

const config = [
  {
    test: isOldPlayer,
    supports: {
      playpause: true,
      previous: true,
      next: true
    },
    playStateSelector: '.player-control',
    playStateClass: 'pause-state',
    playPauseSelector: '.player-control',
    titleSelector: '.player-cloudcast-title',
    artistSelector: '.player-cloudcast-author-link',
    artworkImageSelector: '.player-cloudcast-image img'
  },
  {
    test: isNewPlayer,
    supports: {
      playpause: true,
      previous: true,
      next: true
    },
    playStateSelector: '.mz-player-control',
    playStateClass: 'mz-pause-state',
    playPauseSelector: '.mz-player-control',
    titleSelector: '.mz-player-cloudcast-title',
    artistSelector: '.mz-player-cloudcast-author-link',
    artworkImageSelector: '.mz-player-cloudcast-image img'
  }
];

controller = new BasicController(config);

controller.override('getAlbumArt', function(_super) {
  let art = _super();
  return art && art.replace(/\/60\//g, '\/300\/')
                   .replace(/\/60x60\//g, '\/300x300\/');
});

const CUSTOM_EVENT_TYPE = 'mxswayEvent';
function mxTriggerEvent(type) {
  const event = new CustomEvent(CUSTOM_EVENT_TYPE, { detail: type });
  document.dispatchEvent(event);
}

controller.override('nextSong', function() {
  mxTriggerEvent('next');
});

controller.override('previousSong', function() {
  mxTriggerEvent('prev');
});

const scrubbingCode = `
(function() {
  const SCRUBBER_SELECTOR_OLD = '.player-scrubber';
  const SCRUBBER_SELECTOR_NEW = '.mz-player-scrubber';
  const SKIP_TIME = 60; // 1 minute

  const getScrubberScope = (function() {
    let scope;

    return function() {
      if (!scope) {
        let $scrubber = $(SCRUBBER_SELECTOR_OLD);
        $scrubber = ($scrubber.length > 0) ? $scrubber : $(SCRUBBER_SELECTOR_NEW);
        scope = $scrubber.scope();
      }

      return scope;
    };
  })();

  function scrub(type) {
    const delta = type === 'next' ? SKIP_TIME : -SKIP_TIME;
    moveScrubber(delta);
  }

  function getNewPosition(delta) {
    const { audioPosition, audioLength } = getScrubberScope().player;

    // setup new time, and check for overflow
    let position = audioPosition + delta;

    if (position > audioLength) {
      position = audioLength;
    } else if (position < 0) {
      position = 0;
    }

    return position;
  }

  function moveScrubber(delta) {
    getScrubberScope().$emit('slider:stop', getNewPosition(delta));
  }

  document.addEventListener('${CUSTOM_EVENT_TYPE}', function ({ detail: type }) {
    scrub(type);
  });
}());
`;

controller.runInPage(scrubbingCode);
<|endoftext|>


<commit_before>/*
 * libquassel
 * https://github.com/magne4000/node-libquassel
 *
 * Copyright (c) 2014 Joël Charles
 * Licensed under the MIT license.
 */

var Glouton = require('./glouton'),
    serialize = require('./serializer').serialize,
    IRCUser = require('./user'),
    IRCBufferCollection = require('./buffer').IRCBufferCollection,
    HashMap = require('./hashmap');

var Network = function Network(networkId) {
    serialize(this);

    this.networkId = networkId;
    this.buffers = new IRCBufferCollection();
    this.nickUserMap = {}; // HashMap<String, IrcUser>
    this.open = false;
    this.connectionState = Network.ConnectionState.Disconnected;
    this.isConnected = false;
    this.latency = 0;
    this.statusBuffer = null;
    this.networkName = null;
    this.nick = null;
    this.server = null;
};

Glouton.extend(Network);

var NetworkCollection = function NetworkCollection() {
    serialize(this);
    this.hm = new HashMap();
};

NetworkCollection.prototype.add = function(networkid) {
    networkid = parseInt(networkid, 10);
    this.hm.set(networkid, new Network(networkid));
    return this.hm.get(networkid);
};

NetworkCollection.prototype.set = function(networkid, network) {
    networkid = parseInt(networkid, 10);
    this.hm.set(networkid, network);
    return network;
};

NetworkCollection.prototype.get = function(networkid) {
    networkid = parseInt(networkid, 10);
    return this.hm.get(networkid);
};

NetworkCollection.prototype.remove = function(networkid) {
    networkid = parseInt(networkid, 10);
    this.hm.remove(networkid);
};

NetworkCollection.prototype.findBuffer = function(bufferId) {
    if (typeof bufferId !== "number") return null;
    var networks = this.hm.values(), ind;
    for (ind in networks) {
        if (networks[ind].getBufferCollection().hasBuffer(bufferId)) {
            return networks[ind].getBufferCollection().getBuffer(bufferId);
        }
    }
    return null;
};

NetworkCollection.prototype.removeBuffer = function(bufferId) {
    var buffer = this.findBuffer(bufferId);
    if (buffer !== null) {
        this.get(buffer.network).getBufferCollection().removeBuffer(bufferId);
    }
};

NetworkCollection.prototype.all = function() {
    return this.hm.values();
};

Network.ConnectionState = {
    Disconnected: 0,
    Connecting: 1,
    Initializing: 2,
    Initialized: 3,
    Reconnecting: 4,
    Disconnecting: 5
};

/**
 * @param {string} networkName
 */
Network.prototype.setName = function(networkName) {
    this.networkName = networkName;
    this.updateTopic();
};

/**
 * @param {Array<IrcUser>} networkName
 */
Network.prototype.setUserList = function(userList) {
    var i;
    this.nickUserMap.clear();
    if (userList !== null && userList.length> 0) {
        for (i=0; i<userList.length; i++) {
            this.nickUserMap.put(userList[i].nick, userList[i]);
        }
    }
};

/**
 * @param {string} oldNick
 * @param {string} newNick
 */
Network.prototype.renameUser = function(oldNick, newNick) {
    var user = this.getUserByNick(oldNick);
    user.nick = newNick;
    this.nickUserMap[newNick] = user;
    delete this.nickUserMap[oldNick];
};

/**
 * @param {IrcUser} user
 */
Network.prototype.addUser = function(user) {
    this.nickUserMap[user.nick] = user;
};

/**
 * @param {string} nick
 */
Network.prototype.removeUser = function(nick) {
    // remove user from channels
    // and disable user buffer
    var ircuser = this.getUserByNick(nick);
    var self = this;
    this.getBufferHashMap().forEach(function(value, key){
        if (value.isChannel()) {
            if (value.hasUser(ircuser)) {
                value.removeUser(ircuser);
            }
        } else if (value.name === nick) {
            value.setActive(false);
        }
    });
    delete this.nickUserMap[nick];
};

/**
 * @param {string} nick
 */
Network.prototype.hasNick = function(nick) {
    return nick in this.nickUserMap;
};

/**
 * @param {string} nick
 */
Network.prototype.getUserByNick = function(nick) {
    return this.nickUserMap[nick];
};

/**
 * @param {boolean} connected
 */
Network.prototype.setConnected = function(connected) {
    if (connected) {
        //this.setOpen(true);
        if (this.statusBuffer !== null) {
            this.statusBuffer.setActive(true);
        }
    } else {
        //this.setOpen(false);
        if (this.statusBuffer !== null) {
            this.statusBuffer.setActive(false);
        }
        /* TODO
        for (Buffer buffer : buffers.getRawBufferList()) {
            buffer.setActive(false);
        }
        */
    }
    this.isConnected = connected;
};

/**
 * @param {Object} uac
 */
Network.prototype.setIrcUsersAndChannels = function(uac) {
    var key, user, channel, nick;

    // Create IRCUsers and attach them to network
    for (key in uac.users) {
        user = new IRCUser(key, uac.users[key]);
        this.nickUserMap[user.nick] = user;
    }
    // Create Channels and attach them to network
    for (key in uac.channels) {
        channel = this.getBuffer(key);
        //Then attach users to channels
        for (nick in uac.channels[key].UserModes) {
            user = this.getUserByNick(nick);
            if (typeof user !== 'undefined') {
                channel.addUser(user, uac.channels[key].UserModes[nick]);
            } else {
                console.log("User " + nick + " have not been found on server.");
            }
        }
    }
};

/**
 * @param {number} latency
 */
Network.prototype.setLatency = function(latency) {
    this.latency = latency;
};

/**
 * @param {string} server
 */
Network.prototype.setServer = function(server) {
    this.server = server;
};

/**
 */
Network.prototype.updateTopic = function() {
    if (this.statusBuffer !== null) {
        this.statusBuffer.setTopic("");
    }
};

/**
 * @param {IRCBuffer} statusBuffer
 */
Network.prototype.setStatusBuffer = function(statusBuffer) {
    this.statusBuffer = statusBuffer;
};

/**
 * @returns {IRCBuffer}
 */
Network.prototype.getStatusBuffer = function() {
    return this.statusBuffer;
};

/**
 * @returns {IRCBufferCollection}
 */
Network.prototype.getBufferCollection = function() {
    return this.buffers;
};

/**
 * @returns {HashMap}
 */
Network.prototype.getBufferHashMap = function() {
    return this.buffers.buffers;
};

/**
 */
Network.prototype.getBuffer = function(ind) {
    return this.buffers.getBuffer(ind);
};

exports.Network = Network;
exports.NetworkCollection = NetworkCollection;
<commit_msg>getUserByNick now returns null if user not found<commit_after>/*
 * libquassel
 * https://github.com/magne4000/node-libquassel
 *
 * Copyright (c) 2014 Joël Charles
 * Licensed under the MIT license.
 */

var Glouton = require('./glouton'),
    serialize = require('./serializer').serialize,
    IRCUser = require('./user'),
    IRCBufferCollection = require('./buffer').IRCBufferCollection,
    HashMap = require('./hashmap');

var Network = function Network(networkId) {
    serialize(this);

    this.networkId = networkId;
    this.buffers = new IRCBufferCollection();
    this.nickUserMap = {}; // HashMap<String, IrcUser>
    this.open = false;
    this.connectionState = Network.ConnectionState.Disconnected;
    this.isConnected = false;
    this.latency = 0;
    this.statusBuffer = null;
    this.networkName = null;
    this.nick = null;
    this.server = null;
};

Glouton.extend(Network);

var NetworkCollection = function NetworkCollection() {
    serialize(this);
    this.hm = new HashMap();
};

NetworkCollection.prototype.add = function(networkid) {
    networkid = parseInt(networkid, 10);
    this.hm.set(networkid, new Network(networkid));
    return this.hm.get(networkid);
};

NetworkCollection.prototype.set = function(networkid, network) {
    networkid = parseInt(networkid, 10);
    this.hm.set(networkid, network);
    return network;
};

NetworkCollection.prototype.get = function(networkid) {
    networkid = parseInt(networkid, 10);
    return this.hm.get(networkid);
};

NetworkCollection.prototype.remove = function(networkid) {
    networkid = parseInt(networkid, 10);
    this.hm.remove(networkid);
};

NetworkCollection.prototype.findBuffer = function(bufferId) {
    if (typeof bufferId !== "number") return null;
    var networks = this.hm.values(), ind;
    for (ind in networks) {
        if (networks[ind].getBufferCollection().hasBuffer(bufferId)) {
            return networks[ind].getBufferCollection().getBuffer(bufferId);
        }
    }
    return null;
};

NetworkCollection.prototype.removeBuffer = function(bufferId) {
    var buffer = this.findBuffer(bufferId);
    if (buffer !== null) {
        this.get(buffer.network).getBufferCollection().removeBuffer(bufferId);
    }
};

NetworkCollection.prototype.all = function() {
    return this.hm.values();
};

Network.ConnectionState = {
    Disconnected: 0,
    Connecting: 1,
    Initializing: 2,
    Initialized: 3,
    Reconnecting: 4,
    Disconnecting: 5
};

/**
 * @param {string} networkName
 */
Network.prototype.setName = function(networkName) {
    this.networkName = networkName;
    this.updateTopic();
};

/**
 * @param {Array<IrcUser>} networkName
 */
Network.prototype.setUserList = function(userList) {
    var i;
    this.nickUserMap.clear();
    if (userList !== null && userList.length> 0) {
        for (i=0; i<userList.length; i++) {
            this.nickUserMap.put(userList[i].nick, userList[i]);
        }
    }
};

/**
 * @param {string} oldNick
 * @param {string} newNick
 */
Network.prototype.renameUser = function(oldNick, newNick) {
    var user = this.getUserByNick(oldNick);
    user.nick = newNick;
    this.nickUserMap[newNick] = user;
    delete this.nickUserMap[oldNick];
};

/**
 * @param {IrcUser} user
 */
Network.prototype.addUser = function(user) {
    this.nickUserMap[user.nick] = user;
};

/**
 * @param {string} nick
 */
Network.prototype.removeUser = function(nick) {
    // remove user from channels
    // and disable user buffer
    var ircuser = this.getUserByNick(nick);
    var self = this;
    this.getBufferHashMap().forEach(function(value, key){
        if (value.isChannel()) {
            if (value.hasUser(ircuser)) {
                value.removeUser(ircuser);
            }
        } else if (value.name === nick) {
            value.setActive(false);
        }
    });
    delete this.nickUserMap[nick];
};

/**
 * @param {string} nick
 */
Network.prototype.hasNick = function(nick) {
    return nick in this.nickUserMap;
};

/**
 * @param {string} nick
 */
Network.prototype.getUserByNick = function(nick) {
    return this.nickUserMap[nick] || null;
};

/**
 * @param {boolean} connected
 */
Network.prototype.setConnected = function(connected) {
    if (connected) {
        //this.setOpen(true);
        if (this.statusBuffer !== null) {
            this.statusBuffer.setActive(true);
        }
    } else {
        //this.setOpen(false);
        if (this.statusBuffer !== null) {
            this.statusBuffer.setActive(false);
        }
        /* TODO
        for (Buffer buffer : buffers.getRawBufferList()) {
            buffer.setActive(false);
        }
        */
    }
    this.isConnected = connected;
};

/**
 * @param {Object} uac
 */
Network.prototype.setIrcUsersAndChannels = function(uac) {
    var key, user, channel, nick;

    // Create IRCUsers and attach them to network
    for (key in uac.users) {
        user = new IRCUser(key, uac.users[key]);
        this.nickUserMap[user.nick] = user;
    }
    // Create Channels and attach them to network
    for (key in uac.channels) {
        channel = this.getBuffer(key);
        //Then attach users to channels
        for (nick in uac.channels[key].UserModes) {
            user = this.getUserByNick(nick);
            if (user !== null) {
                channel.addUser(user, uac.channels[key].UserModes[nick]);
            } else {
                console.log("User " + nick + " have not been found on server.");
            }
        }
    }
};

/**
 * @param {number} latency
 */
Network.prototype.setLatency = function(latency) {
    this.latency = latency;
};

/**
 * @param {string} server
 */
Network.prototype.setServer = function(server) {
    this.server = server;
};

/**
 */
Network.prototype.updateTopic = function() {
    if (this.statusBuffer !== null) {
        this.statusBuffer.setTopic("");
    }
};

/**
 * @param {IRCBuffer} statusBuffer
 */
Network.prototype.setStatusBuffer = function(statusBuffer) {
    this.statusBuffer = statusBuffer;
};

/**
 * @returns {IRCBuffer}
 */
Network.prototype.getStatusBuffer = function() {
    return this.statusBuffer;
};

/**
 * @returns {IRCBufferCollection}
 */
Network.prototype.getBufferCollection = function() {
    return this.buffers;
};

/**
 * @returns {HashMap}
 */
Network.prototype.getBufferHashMap = function() {
    return this.buffers.buffers;
};

/**
 */
Network.prototype.getBuffer = function(ind) {
    return this.buffers.getBuffer(ind);
};

exports.Network = Network;
exports.NetworkCollection = NetworkCollection;
<|endoftext|>


<commit_before>/*
Copyright 2015 OpenMarket Ltd

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.
*/

'use strict';

var dis = require("../../dispatcher");

module.exports = {
    onClick: function() {
        dis.dispatch({
            action: 'logout'
        });
    },
};
<commit_msg>Nuke LogoutButton; nothing used it.<commit_after><|endoftext|>