<commit_before>'use strict';

var $ = require('jquery'),
    _ = require('underscore'),
    L = require('leaflet'),
    Backbone = require('../../shim/backbone'),
    Marionette = require('../../shim/backbone.marionette'),
    moment = require('moment'),
    PlotView = require('./modals/views').PlotView,
    measurementTmpl = require('./templates/measurement.html'),
    measurementsTmpl = require('./templates/measurements.html'),
    popupTmpl = require('./templates/observationPopup.html'),
    vizerUrls = require('./settings').get('vizer_urls'),
    vizerIgnore = require('./settings').get('vizer_ignore'),
    vizerNames = require('./settings').get('vizer_names');

// These are likely temporary until we develop custom icons for each type
var platformIcons = {
        'River Guage': '#F44336',
        'Weather Station': '#4CAF50',
        'Fixed Shore Platform': '#2196F3',
        'Soil Pit': '#FFEB3B',
        'Well': '#795548'
    },
    error_msg = 'Unable to load Observation data';

function VizerLayers() {
    var layersReady = $.Deferred();

    this.getLayers = function() {
        // If there are problems with the vizer URLs, don't hold up the creation
        // of the layer selector
        if (!vizerUrls.layers) {
            layersReady.resolve();
        }

        $.getJSON(vizerUrls.layers)
            .done(function(assets) {
                if (!assets.success) {
                    layersReady.reject(error_msg);
                }

                // A list of all assets (typically sensor devices) and the variables
                // they manage, along with various meta data grouped by the data
                // provider which acts as the "layer" which can be toggled on/off
                var layerAssets = _.omit(_.groupBy(assets.result, 'provider'), vizerIgnore);
                var layers = _.map(layerAssets, function(assets, provider) {

                    // Create a marker for each asset point in this layer and
                    // use the appropriate style for the platform type
                    var label = makeProviderLabel(provider, assets),
                        markers = _.map(assets, function(asset) {
                            var color = _.has(platformIcons, asset.platform_type) ?
                                    platformIcons[asset.platform_type] :
                                    '#607D8B';

                            return L.circleMarker([asset.lat, asset.lon], {
                                attributes: asset,
                                fillColor: color,
                                fillOpacity: 1.0
                            });
                        });

                    var layer = L.featureGroup(markers);
                    attachPopups(layer);

                    return [label, layer];
                });

                // All layers are loaded have have markers created for all assets
                layersReady.resolve(_.object(layers));
            })
            .fail(function() {
                layersReady.reject(error_msg);
            });

        return layersReady;
    };
}

function makeProviderLabel(provider, assets) {
    // Create a label for the layer selector.
    return (vizerNames[provider] || provider) + ' (' + assets.length + ')';
}

function attachPopups(featureGroup) {
    featureGroup.eachLayer(function(marker) {
        var model = new Backbone.Model(marker.options.attributes),
            view = new ObservationPopupView({model: model});

        marker.bindPopup(view.render().el);
        marker.on('popupopen', function(popupEvent) {
            // When the popup is opened, fetch the recent values of
            // this asset's measurements and update the Popup
            var id = popupEvent.target.options.attributes.siso_id,
                url =  vizerUrls.recent.replace(/{{asset_id}}/, id);

            $.getJSON(url, _.partial(updatePopup, popupEvent.popup, model));
        });
    });
}

/* Update an existing popup with model values merged with a single measurement
 * result for each category (variable) available in the asset */
function updatePopup(popup, model, recentValues) {
    var values = _.map(model.get('measurements'), function(category) {
        var measurement = _.findWhere(recentValues.result, {var_id: category.var_id});

        if (measurement) {
            measurement.lastUpdated = new Date(measurement.time * 1000); // seconds -> ms
        }

        return _.extend(category, measurement);
    });

    model.set('measurements', values);

    var view = new ObservationPopupView({model: model});
    popup.setContent(view.render().el);
    popup.update();
}

var MeasurementView = Marionette.LayoutView.extend({
    tagName: 'tr',

    template: measurementTmpl,

    initialize: function(options) {
        this.options = options;
        this.model.set('showDepth', false);
    },

    ui: {
        'data': '.measurement-data'
    },

    events: {
        'click': 'showPlot'
    },

    showPlot: function() {
        this.options.showPlot(this.model.get('var_id'));
    }
});

var MeasurementsView = Marionette.CompositeView.extend({
    template: measurementsTmpl,

    childView: MeasurementView,

    childViewContainer: 'tbody',

    initialize: function(options) {
        this.options = options;
    },

    childViewOptions: function() {
        return this.options;
    }
});

var ObservationPopupView = Marionette.LayoutView.extend({
    template: popupTmpl,

    className: 'observation-popup',

    ui: {
        showPlotButton: 'button.show-plot'
    },

    events: {
        'click @ui.showPlotButton': 'showDefaultPlot'
    },

    regions: {
        measurementsRegion: '.measurements-region'
    },

    templateHelpers: function() {
        var measurements = this.model.get('measurements'),
            lastUpdatedTimes = _.pluck(measurements, 'lastUpdated'),
            latestTime = _.reduce(lastUpdatedTimes, function(latestTime, time) {
                if (time > latestTime) {
                    return time;
                }
                return latestTime;
            }),
            provider = this.model.get('provider'),
            providerName =
                provider === "NOS/CO-OPS" ?
                    provider :
                    vizerNames[provider];
        return {
            lastUpdated: moment(latestTime).fromNow(),
            providerName: providerName,
        };
    },

    onRender: function() {
        this.measurementsRegion.show(new MeasurementsView({
            collection: new Backbone.Collection(this.model.get('measurements')),
            showPlot: _.bind(this.showPlot, this)
        }));
    },

    showDefaultPlot: function() {
        this.showPlot(this.model.get('measurements')[0].var_id);
    },

    showPlot: function(varId) {
        var plotModel = new Backbone.Model(_.extend(this.model.attributes, {
            currVarId: varId
        }));

        this.detailModal = new PlotView({model: plotModel}).render();
    }
});

module.exports = VizerLayers;
<commit_msg>Update observation colors<commit_after>'use strict';

var $ = require('jquery'),
    _ = require('underscore'),
    L = require('leaflet'),
    Backbone = require('../../shim/backbone'),
    Marionette = require('../../shim/backbone.marionette'),
    moment = require('moment'),
    PlotView = require('./modals/views').PlotView,
    measurementTmpl = require('./templates/measurement.html'),
    measurementsTmpl = require('./templates/measurements.html'),
    popupTmpl = require('./templates/observationPopup.html'),
    vizerUrls = require('./settings').get('vizer_urls'),
    vizerIgnore = require('./settings').get('vizer_ignore'),
    vizerNames = require('./settings').get('vizer_names');

// These are likely temporary until we develop custom icons for each type
var platformIcons = {
        'River Guage': '#10A579',
        'Weather Station': '#F2B703',
        'Fixed Shore Platform': '#7FB95A',
        'Soil Pit': '#CF1D90',
        'Well': '#A5A998'
    },
    error_msg = 'Unable to load Observation data';

function VizerLayers() {
    var layersReady = $.Deferred();

    this.getLayers = function() {
        // If there are problems with the vizer URLs, don't hold up the creation
        // of the layer selector
        if (!vizerUrls.layers) {
            layersReady.resolve();
        }

        $.getJSON(vizerUrls.layers)
            .done(function(assets) {
                if (!assets.success) {
                    layersReady.reject(error_msg);
                }

                // A list of all assets (typically sensor devices) and the variables
                // they manage, along with various meta data grouped by the data
                // provider which acts as the "layer" which can be toggled on/off
                var layerAssets = _.omit(_.groupBy(assets.result, 'provider'), vizerIgnore);
                var layers = _.map(layerAssets, function(assets, provider) {

                    // Create a marker for each asset point in this layer and
                    // use the appropriate style for the platform type
                    var label = makeProviderLabel(provider, assets),
                        markers = _.map(assets, function(asset) {
                            var color = _.has(platformIcons, asset.platform_type) ?
                                    platformIcons[asset.platform_type] :
                                    '#607D8B';

                            return L.circleMarker([asset.lat, asset.lon], {
                                attributes: asset,
                                fillColor: color,
                                fillOpacity: 0.6,
                                color: color
                            });
                        });

                    var layer = L.featureGroup(markers);
                    attachPopups(layer);

                    return [label, layer];
                });

                // All layers are loaded have have markers created for all assets
                layersReady.resolve(_.object(layers));
            })
            .fail(function() {
                layersReady.reject(error_msg);
            });

        return layersReady;
    };
}

function makeProviderLabel(provider, assets) {
    // Create a label for the layer selector.
    return (vizerNames[provider] || provider) + ' (' + assets.length + ')';
}

function attachPopups(featureGroup) {
    featureGroup.eachLayer(function(marker) {
        var model = new Backbone.Model(marker.options.attributes),
            view = new ObservationPopupView({model: model});

        marker.bindPopup(view.render().el);
        marker.on('popupopen', function(popupEvent) {
            // When the popup is opened, fetch the recent values of
            // this asset's measurements and update the Popup
            var id = popupEvent.target.options.attributes.siso_id,
                url =  vizerUrls.recent.replace(/{{asset_id}}/, id);

            $.getJSON(url, _.partial(updatePopup, popupEvent.popup, model));
        });
    });
}

/* Update an existing popup with model values merged with a single measurement
 * result for each category (variable) available in the asset */
function updatePopup(popup, model, recentValues) {
    var values = _.map(model.get('measurements'), function(category) {
        var measurement = _.findWhere(recentValues.result, {var_id: category.var_id});

        if (measurement) {
            measurement.lastUpdated = new Date(measurement.time * 1000); // seconds -> ms
        }

        return _.extend(category, measurement);
    });

    model.set('measurements', values);

    var view = new ObservationPopupView({model: model});
    popup.setContent(view.render().el);
    popup.update();
}

var MeasurementView = Marionette.LayoutView.extend({
    tagName: 'tr',

    template: measurementTmpl,

    initialize: function(options) {
        this.options = options;
        this.model.set('showDepth', false);
    },

    ui: {
        'data': '.measurement-data'
    },

    events: {
        'click': 'showPlot'
    },

    showPlot: function() {
        this.options.showPlot(this.model.get('var_id'));
    }
});

var MeasurementsView = Marionette.CompositeView.extend({
    template: measurementsTmpl,

    childView: MeasurementView,

    childViewContainer: 'tbody',

    initialize: function(options) {
        this.options = options;
    },

    childViewOptions: function() {
        return this.options;
    }
});

var ObservationPopupView = Marionette.LayoutView.extend({
    template: popupTmpl,

    className: 'observation-popup',

    ui: {
        showPlotButton: 'button.show-plot'
    },

    events: {
        'click @ui.showPlotButton': 'showDefaultPlot'
    },

    regions: {
        measurementsRegion: '.measurements-region'
    },

    templateHelpers: function() {
        var measurements = this.model.get('measurements'),
            lastUpdatedTimes = _.pluck(measurements, 'lastUpdated'),
            latestTime = _.reduce(lastUpdatedTimes, function(latestTime, time) {
                if (time > latestTime) {
                    return time;
                }
                return latestTime;
            }),
            provider = this.model.get('provider'),
            providerName =
                provider === "NOS/CO-OPS" ?
                    provider :
                    vizerNames[provider];
        return {
            lastUpdated: moment(latestTime).fromNow(),
            providerName: providerName,
        };
    },

    onRender: function() {
        this.measurementsRegion.show(new MeasurementsView({
            collection: new Backbone.Collection(this.model.get('measurements')),
            showPlot: _.bind(this.showPlot, this)
        }));
    },

    showDefaultPlot: function() {
        this.showPlot(this.model.get('measurements')[0].var_id);
    },

    showPlot: function(varId) {
        var plotModel = new Backbone.Model(_.extend(this.model.attributes, {
            currVarId: varId
        }));

        this.detailModal = new PlotView({model: plotModel}).render();
    }
});

module.exports = VizerLayers;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';
import styled from 'styled-components';
import { Control, Form, actions } from 'react-redux-form';
import axios from 'axios';
import { browserHistory } from 'react-router';
import Script from 'react-load-script'

import {fetchBraintreeToken, sendPostcards} from './actions';
import MainHeader from 'components/MainHeader';
import Button from 'components/Button';
import RepCard from './repCard';
import RepForm from './RepForm';
import Img from 'components/Img';
import LoadingIndicator from 'components/LoadingIndicator';

const braintree = require('braintree-web');

const RepCardBox = styled.div`
  .circle-img {
    overflow: hidden;
    display:inline;
    height: 6rem;
    margin-bottom: 1.5rem;
    border-radius: 50%;
  }
`;

export class Representatives extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function

  constructor(props) {
    super(props);
    this.state = {
      braintreeToken: null,
      loading: false
    }
  }

  componentDidMount() {
    const self = this;
    return axios.get(`/api/payments/client-token`)
    .then(function(res){
      return Promise.resolve(braintree.client.create({
        authorization: res.data.clientToken
      }))
    })
    .then(function(data){
      return self.clientDidCreate(data);
    })
  }

  componentWillUnmount() {
    this.props.dispatch(actions.reset('selectedReps.selected'));
  }

  clientDidCreate(client) {
    const self = this;

    return Promise.resolve(braintree.paypalCheckout.create({
      client: client
    }))
    .then(function(paypalCheckoutInstance) {
      return paypal.Button.render({
        env: 'sandbox',
        locale: 'en_US',

        payment: function() {
          return paypalCheckoutInstance.createPayment({
            flow: 'vault'
          })
        },

        onAuthorize: function(data, actions) {
          return paypalCheckoutInstance.tokenizePayment(data).then(function (payload){

            self.setState({loading: true})

            return self.props.sendPostcards({
              nonce: payload.nonce,
              issueId: self.props.routeParams.id,
              representatives: self.props.selectedReps.selected,
              user: self.props.user
            })
            .then(function(res){
              self.setState({ loading: false });
              self.props.dispatch(actions.reset('selectedReps.selected'));
              browserHistory.push(`/confirmation`)
            })
          })
        },

        onError: function(err){
          console.error('checkout.js error', err);
        }
      }, "#paypal-button")
    })
  }

  createRepCard(representative, index) {
    if (!representative) return;
    const address = representative.address[0];

    return (
      <div className={`col-md-3 col-sm-12 rep_content ${representative.party.toLowerCase()}`} key={representative.name}>

<Control.checkbox model='.selected[]' value={JSON.stringify(representative)} id={`rep_${index}`} className="big_checkbox" />
        <label htmlFor={`rep_${index}`} className="btn">
        <RepCardBox>

{`${representative.name}, ${representative.party[0]}`}

{`${address.line1}, ${address.city}, ${address.state}, ${address.zip}`}

        </RepCardBox>

    )
  }

  createRepCards() {
    return this.props.representatives.map((representative, index) => {
      if (index%2 !== 0) return;

      return (

            {this.createRepCard(representative, index)}
            {this.createRepCard(this.props.representatives[index+1], index+1)}

      )
    })
  }

  render() {
    return (


<commit_before>import React from 'react'
import classNames from 'classnames'
import { TextInputAndSelect } from 'kitten/components/form/text-input-and-select'

export const FormAmountAndCurrency = props => {
  const { currencyOptions,
          currencyName,
          currencyValue,
          ...textInputAndSelectProps } = props

  return (
    <TextInputAndSelect
      selectOptions={ currencyOptions }
      selectName={ currencyName }
      selectValue={ currencyValue }
      key={ currencyName }
      type="number"
      { ...textInputAndSelectProps } />
  )
}

FormAmountAndCurrency.defaultProps = {
  tiny: false,
  disabled: false,
  currencyOptions: [{ value: 'eur', label: 'EUR' }],
  currencyName: null,
  currencyValue: null,
  digits: null, // 2 or 12 for now
}
<commit_msg>Minor FormAmountAndCurrency syntax fix (#988)<commit_after>import React from 'react'
import classNames from 'classnames'
import { TextInputAndSelect } from 'kitten/components/form/text-input-and-select'

export const FormAmountAndCurrency = props => {
  const {
    currencyOptions,
    currencyName,
    currencyValue,
    ...textInputAndSelectProps
  } = props

  return (
    <TextInputAndSelect
      selectOptions={ currencyOptions }
      selectName={ currencyName }
      selectValue={ currencyValue }
      key={ currencyName }
      type="number"
      { ...textInputAndSelectProps }
    />
  )
}

FormAmountAndCurrency.defaultProps = {
  tiny: false,
  disabled: false,
  currencyOptions: [{ value: 'eur', label: 'EUR' }],
  currencyName: null,
  currencyValue: null,
  digits: null, // 2 or 12 for now
}
<|endoftext|>


<commit_before>$ch.define("node",function(){"use strict";var e=function(){var n={_node:void 0,context:function(){return this._node},parent:function(){var n=e();return n._node=this._node.parentNode,n},child:function(){for(var n=this._node.childNodes,t=[],r=0,i=n.length;r!==i;++r){var o=n[r],s=e();s._node=o,t.push(s)}return t},contains:function(e){if(0===arguments.length)throw new Error(".contains requires a chop.js node parameter.");for(var n=this._node.childNodes,t=!1,r=0,i=n.length;r!==i;++r){var o=n[r];o===e._node&&(t=!0)}return t},next:function(){var n=e();return n._node=this._node.nextElementSibling,n},previous:function(){var n=e();return n._node=this._node.previousElementSibling,n},html:function(e){return 0===arguments.length?this._node.innerHTML:(this._node.innerHTML=e,$$CHOP._loadView(this._node),this)},append:function(e){return void 0!==e&&this.html(this._node.innerHTML+e),this},prepend:function(e){return void 0!==e&&this.html(e+this._node.innerHTML),this},className:function(e){if(void 0!==e){var n=!0;if($$CHOP.isArray(e)){var t=this;$$CHOP.each(e,function(e){-1===t._node.className.indexOf(e)&&(n=!1)})}else-1===this._node.className.indexOf(e)&&(n=!1);return n}return this._node.className},addClass:function(e){if(void 0!==e)if($$CHOP.isArray(e)){var n=this;$$CHOP.each(e,function(e){n._node.className+=e+" "})}else this._node.className+=e+" ";return this},removeClass:function(e){if(void 0!==e){var n;$$CHOP.isArray(e)?(n=this._node.className,$$CHOP.each(e,function(e){n=n.replace(e,"")}),this._node.className=n.replace(e,"")):(n=this._node.className,this._node.className=n.replace(e,""))}return this},attr:function(e,n){return 0===arguments.length?this._node.attributes:1===arguments.length?this._node.getAttribute(e):(this._node.setAttribute(e,n),this)}};return n};$$CHOPEL.node=function(){var n=e();return n._node=this.el,n},$$CHOPEL.child=function(){for(var n=this.el.childNodes,t=[],r=0,i=n.length;r!==i;++r){var o=n[r],s=e();s._node=o,t.push(s)}return t},$$CHOP.node=function(n,t){if(0===arguments.length)throw new Error("$ch.node requires at least one tag-name parameter.");var r=document.createElement(n);void 0!==t&&(r.innerHTML=t);var i=e();return i._node=r,i},$$CHOPEL.appendNode=function(e){if(0===arguments.length)throw new Error(".appendNode requires a node parameter.");this.el.appendChild(e._node),$$CHOP._loadView(this.el)},$$CHOPEL.removeNode=function(e){if(0===arguments.length)throw new Error(".removeNode requires a node parameter.");this.el.removeChild(e._node),$$CHOP._loadView(this.el)}});<commit_msg>node object append/remove node<commit_after>$ch.define("node",function(){"use strict";var e=function(){var n={_node:void 0,context:function(){return this._node},parent:function(){var n=e();return n._node=this._node.parentNode,n},child:function(){for(var n=this._node.childNodes,t=[],r=0,o=n.length;r!==o;++r){var i=n[r],s=e();s._node=i,t.push(s)}return t},contains:function(e){if(0===arguments.length)throw new Error(".contains requires a chop.js node parameter.");for(var n=this._node.childNodes,t=!1,r=0,o=n.length;r!==o;++r){var i=n[r];i===e._node&&(t=!0)}return t},next:function(){var n=e();return n._node=this._node.nextElementSibling,n},previous:function(){var n=e();return n._node=this._node.previousElementSibling,n},html:function(e){return 0===arguments.length?this._node.innerHTML:(this._node.innerHTML=e,$$CHOP._loadView(this._node),this)},append:function(e){return void 0!==e&&this.html(this._node.innerHTML+e),this},prepend:function(e){return void 0!==e&&this.html(e+this._node.innerHTML),this},className:function(e){if(void 0!==e){var n=!0;if($$CHOP.isArray(e)){var t=this;$$CHOP.each(e,function(e){-1===t._node.className.indexOf(e)&&(n=!1)})}else-1===this._node.className.indexOf(e)&&(n=!1);return n}return this._node.className},addClass:function(e){if(void 0!==e)if($$CHOP.isArray(e)){var n=this;$$CHOP.each(e,function(e){n._node.className+=e+" "})}else this._node.className+=e+" ";return this},removeClass:function(e){if(void 0!==e){var n;$$CHOP.isArray(e)?(n=this._node.className,$$CHOP.each(e,function(e){n=n.replace(e,"")}),this._node.className=n.replace(e,"")):(n=this._node.className,this._node.className=n.replace(e,""))}return this},attr:function(e,n){return 0===arguments.length?this._node.attributes:1===arguments.length?this._node.getAttribute(e):(this._node.setAttribute(e,n),this)},appendNode:function(e){if(0===arguments.length)throw new Error(".appendNode requires a node parameter.");this._node.appendChild(e._node),$$CHOP._loadView(this._node)},removeNode:function(e){if(0===arguments.length)throw new Error(".removeNode requires a node parameter.");this._node.removeChild(e._node),$$CHOP._loadView(this._node)}};return n};$$CHOPEL.node=function(){var n=e();return n._node=this.el,n},$$CHOPEL.child=function(){for(var n=this.el.childNodes,t=[],r=0,o=n.length;r!==o;++r){var i=n[r],s=e();s._node=i,t.push(s)}return t},$$CHOP.node=function(n,t){if(0===arguments.length)throw new Error("$ch.node requires at least one tag-name parameter.");var r=document.createElement(n);void 0!==t&&(r.innerHTML=t);var o=e();return o._node=r,o},$$CHOPEL.appendNode=function(e){if(0===arguments.length)throw new Error(".appendNode requires a node parameter.");this.el.appendChild(e._node),$$CHOP._loadView(this.el)},$$CHOPEL.removeNode=function(e){if(0===arguments.length)throw new Error(".removeNode requires a node parameter.");this.el.removeChild(e._node),$$CHOP._loadView(this.el)}});<|endoftext|>


<commit_before>var benchpress = require('benchpress');
var runner = new benchpress.Runner([
  benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS,
  benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator),
  benchpress.bind(benchpress.RegressionSlopeValidator.SAMPLE_SIZE).toValue(20),
  benchpress.bind(benchpress.RegressionSlopeValidator.METRIC).toValue('scriptTime'),
  benchpress.bind(benchpress.Options.FORCE_GC).toValue(false)
]);

describe('combineLatest comparison', function () {
  [
    1000,
    10000
  ].forEach(function (val) {
    it('should be fast in Rx2', function (done) {
      browser.ignoreSynchronization = true;
      browser.get('http://localhost:8080/perf/macro/combineLatest/index.html?iterations=' + val);
      runner.sample({
        id: 'combineLatest Rx2',
        execute: function () {
          $('#rx-2-combineLatest').click();
        },
        bindings: [
          benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({
            iterations: val
          })
        ]
      }).then(done, done.fail);
    });

    it('should be fast in RxNext', function (done) {
      browser.ignoreSynchronization = true;
      browser.get('http://localhost:8080/perf/macro/combineLatest/index.html?iterations=' + val);
      runner.sample({
        id: 'combineLatest RxNext',
        execute: function () {
          $('#rx-3-combineLatest').click();
        },
        bindings: [
          benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({
            iterations: val
          })
        ]
      }).then(done, done.fail);
    });
  });
});<commit_msg>refactor(test): let macro test for combinelatest use spec initializer<commit_after>var builder = require('../specbuilder');

var preset = new builder.Preset();
var runner = preset.runner;

describe('combineLatest comparison', function () {
  var testUrlIdentifier = 'combineLatest';

  preset.iteration.forEach(function (val) {

    it('should be fast in Rx2', function (done) {
      preset.initBrowser(browser, testUrlIdentifier, val);
      var param = preset.sampleParameter('combineLatest Rx2', '#rx-2-combineLatest', val);
      runner.sample(param).then(done, done.fail);
    });

    it('should be fast in RxNext', function (done) {
      preset.initBrowser(browser, testUrlIdentifier , val);
      var param = preset.sampleParameter('combineLatest RxNext', '#rx-3-combineLatest', val);
      runner.sample(param).then(done, done.fail);
    });

  });
});<|endoftext|>


<commit_before>import {
  extend
} from '../utils';
import {
  di,
  createHelper
} from '../helpers';
import Bars from './Bars';

/**
  Bars chart with values stacked on top of each other

  (See `Bars` for extensibility details)

  @example
  ```js
  var chart = d3.select('#chart').chart('Compose', function(data) {
    // Display bars for different series next to each other (adjacent: true)
    var xScale = {type: 'ordinal', adjacent: true, domain: [0, 1, 2]};

    return {
      charts: {
        stacked_output: {
          type: 'StackedBars',
          data: data.output,
          xScale: xScale,
          // yScale: ...,
          // other properties...
        }
      }
    };
  });

  // Single y-values
  chart.draw([10, 20, 30]);

  // Series (x,y) values
  chart.draw([
    {values: [{x: 0, y: 10}, {x: 1, y: 20}, {x: 2, y: 30}]},
    {values: [{x: 0, y: 30}, {x: 1, y: 20}, {x: 2, y: 10}]}
  ]);
  ```
  @class StackedBars
  @extends Bars
*/
var StackedBars = Bars.extend({
  transform: function(data) {
    data = Bars.prototype.transform.call(this, data);

    var grouped = {};
    var x_key = this.xKey();
    var y_key = this.yKey();
    data = data.map(function(series) {
      series = extend({}, series);
      series.values = series.values.map(function(value) {
        value = extend({}, value);
        var x = value[x_key];
        var y = value.__original_y = value[y_key];

        if (!grouped[x])
          grouped[x] = {pos: 0, neg: 0};

        if (y >= 0) {
          value.__previous = grouped[x].pos;
          grouped[x].pos = value[y_key] = grouped[x].pos + y;
        }
        else {
          value.__previous = grouped[x].neg;
          grouped[x].neg = value[y_key] = grouped[x].neg + y;
        }

        return value;
      }, this);

      return series;
    }, this);

    return data;
  },

  barHeight: di(function(chart, d, i) {
    var height = Math.abs(chart.yScale()(d.__previous) - chart.y.call(this, d, i));
    var offset = chart.seriesIndex.call(this, d, i) === 0 ? chart.barOffset() : 0;
    return height > 0 ? height - offset : 0;
  })
});

var stackedBars = createHelper('StackedBars');

export {
  StackedBars as default,
  stackedBars
};
<commit_msg>Fix small height issue for stacked bars<commit_after>import {
  extend
} from '../utils';
import {
  di,
  createHelper
} from '../helpers';
import Bars from './Bars';

/**
  Bars chart with values stacked on top of each other

  (See `Bars` for extensibility details)

  @example
  ```js
  var chart = d3.select('#chart').chart('Compose', function(data) {
    // Display bars for different series next to each other (adjacent: true)
    var xScale = {type: 'ordinal', adjacent: true, domain: [0, 1, 2]};

    return {
      charts: {
        stacked_output: {
          type: 'StackedBars',
          data: data.output,
          xScale: xScale,
          // yScale: ...,
          // other properties...
        }
      }
    };
  });

  // Single y-values
  chart.draw([10, 20, 30]);

  // Series (x,y) values
  chart.draw([
    {values: [{x: 0, y: 10}, {x: 1, y: 20}, {x: 2, y: 30}]},
    {values: [{x: 0, y: 30}, {x: 1, y: 20}, {x: 2, y: 10}]}
  ]);
  ```
  @class StackedBars
  @extends Bars
*/
var StackedBars = Bars.extend({
  transform: function(data) {
    data = Bars.prototype.transform.call(this, data);

    var grouped = {};
    var x_key = this.xKey();
    var y_key = this.yKey();
    data = data.map(function(series) {
      series = extend({}, series);
      series.values = series.values.map(function(value) {
        value = extend({}, value);
        var x = value[x_key];
        var y = value.__original_y = value[y_key];

        if (!grouped[x])
          grouped[x] = {pos: 0, neg: 0};

        if (y >= 0) {
          value.__previous = grouped[x].pos;
          grouped[x].pos = value[y_key] = grouped[x].pos + y;
        }
        else {
          value.__previous = grouped[x].neg;
          grouped[x].neg = value[y_key] = grouped[x].neg + y;
        }

        return value;
      }, this);

      return series;
    }, this);

    return data;
  },

  barHeight: di(function(chart, d, i) {
    var height = Math.abs(chart.yScale()(d.__previous) - chart.y.call(this, d, i));
    var offset = chart.seriesIndex.call(this, d, i) === 0 ? chart.barOffset() : 0;
    height = height - offset;
    return height > 0 ? height : 0;
  })
});

var stackedBars = createHelper('StackedBars');

export {
  StackedBars as default,
  stackedBars
};
<|endoftext|>


<commit_before>import React from 'react';
import nl2br from 'react-nl2br';
import _ from 'lodash';
import moment from 'moment';
import SignupButton from './SignupButton';
import SignupList from './SignupList';
import ViewProgress from './ViewProgress';
import EnrollForm from './EnrollForm';
import './SingleEvent.scss';
import allTimesMatch from '../../../utils/allTimesMatch';

class SingleEvent extends React.Component {
  componentWillMount() {
    this.props.getEventInfo(this.props.params.id);
  }
  constructor(props) {
    super(props);
    this.state = {
      formOpened: false,
    };

    this.openForm = this.openForm.bind(this);
    this.closeForm = this.closeForm.bind(this);
    this.submitForm = this.submitForm.bind(this);
  }

  openForm() {
    const state = this.state;
    state.formOpened = true;
    this.setState(state);
  }

  closeForm() {
    const state = this.state;
    state.formOpened = false;
    this.setState(state);
  }

  submitForm() {
    const state = this.state;
    state.formOpened = false;
    this.setState(state);
  }
  render() {
    const event = this.props.singleEvent;

    return (

        {this.state.formOpened ? <EnrollForm closeForm={this.closeForm} /> : '' }

{event.title}

                {event.date ? { moment(event.date).format('D.M.Y [klo] HH:mm') }
 : ''}
                {event.location ? {event.location}
 : ''}
                {event.price ? Hinta: {event.price}
 : ''}
                {event.homepage ? {event.homepage}
 : ''}
                {event.facebook ? Facebook-tapahtuma
 : ''}
                Facebook-tapahtuma

{nl2br(event.description)}

Ilmoittautuminen

                {(event.quotas ? event.quotas.map((quota, index) =>
                  <SignupButton
                    title={quota.title}
                    opens={quota.signupOpens}
                    closes={quota.signupCloses}
                    openForm={this.openForm}
                    isOnly={(event.quotas.length === 1)}
                    // Show label if sign ups times differ or this is the last button
                    showLabel={(allTimesMatch(event.quotas) ? (event.quotas.length === index + 1) : true)}
                    key={index}
                  />,
                  ) : '')}

              {(!_.head(event.quotas) || _.isEmpty(_.head(event.quotas).max) ? '' :

Ilmoittautuneet

                {(event.quotas ? event.quotas.map((quota, index) =>
                  <ViewProgress title={quota.title} value={quota.signups.length} max={quota.size} key={index} />) : '')}

              )}

              {(event.quotas && !event.quotas.length ?
Tapahtuman vastaukset eivät ole julkisia.
 :

Ilmoittautuneet

                {(event.quotas ? event.quotas.map((quota, index) =>
                  <SignupList
                    title={(event.quotas.length > 1 ? quota.title : '')}
                    questions={_.filter(event.questions, 'public')}
                    rows={quota.signups}
                    key={index}
                  />,
                ) : '')}

              )}

    );
  }
}

SingleEvent.propTypes = {
  getEventInfo: React.PropTypes.func.isRequired,
  params: React.PropTypes.shape({
    id: React.PropTypes.string,
  }).isRequired,
  singleEvent: React.PropTypes.shape({
    title: React.PropTypes.string,
    description: React.PropTypes.string,
    price: React.PropTypes.string,
    date: React.PropTypes.string,
    quota: React.PropTypes.array,
  }),
};

export default SingleEvent;
<commit_msg>Fixed quota progress bar showing<commit_after>import React from 'react';
import nl2br from 'react-nl2br';
import _ from 'lodash';
import moment from 'moment';
import SignupButton from './SignupButton';
import SignupList from './SignupList';
import ViewProgress from './ViewProgress';
import EnrollForm from './EnrollForm';
import './SingleEvent.scss';
import allTimesMatch from '../../../utils/allTimesMatch';

class SingleEvent extends React.Component {
  componentWillMount() {
    this.props.getEventInfo(this.props.params.id);
  }
  constructor(props) {
    super(props);
    this.state = {
      formOpened: false,
    };

    this.openForm = this.openForm.bind(this);
    this.closeForm = this.closeForm.bind(this);
    this.submitForm = this.submitForm.bind(this);
  }

  openForm() {
    const state = this.state;
    state.formOpened = true;
    this.setState(state);
  }

  closeForm() {
    const state = this.state;
    state.formOpened = false;
    this.setState(state);
  }

  submitForm() {
    const state = this.state;
    state.formOpened = false;
    this.setState(state);
  }
  render() {
    const event = this.props.singleEvent;

    return (

        {this.state.formOpened ? <EnrollForm closeForm={this.closeForm} /> : '' }

{event.title}

                {event.date ? { moment(event.date).format('D.M.Y [klo] HH:mm') }
 : ''}
                {event.location ? {event.location}
 : ''}
                {event.price ? Hinta: {event.price}
 : ''}
                {event.homepage ? {event.homepage}
 : ''}
                {event.facebook ? Facebook-tapahtuma
 : ''}
                Facebook-tapahtuma

{nl2br(event.description)}

Ilmoittautuminen

                {(event.quotas ? event.quotas.map((quota, index) =>
                  <SignupButton
                    title={quota.title}
                    opens={quota.signupOpens}
                    closes={quota.signupCloses}
                    openForm={this.openForm}
                    isOnly={(event.quotas.length === 1)}
                    // Show label if sign ups times differ or this is the last button
                    showLabel={(allTimesMatch(event.quotas) ? (event.quotas.length === index + 1) : true)}
                    key={index}
                  />,
                  ) : '')}

              {((event.quotas && event.quotas.length) > 1 ?

Ilmoittautuneet

                  {(event.quotas ? event.quotas.map((quota, index) =>
                    <ViewProgress
                      title={quota.title}
                      value={quota.signups.length}
                      max={quota.size}
                      key={index} />,
                    ) : '')}

              : '')}

              {(event.quotas && !event.quotas.length ?
Tapahtuman vastaukset eivät ole julkisia.
 :

Ilmoittautuneet

                {(event.quotas ? event.quotas.map((quota, index) =>
                  <SignupList
                    title={(event.quotas.length > 1 ? quota.title : '')}
                    questions={_.filter(event.questions, 'public')}
                    rows={quota.signups}
                    key={index}
                  />,
                ) : '')}

              )}

    );
  }
}

SingleEvent.propTypes = {
  getEventInfo: React.PropTypes.func.isRequired,
  params: React.PropTypes.shape({
    id: React.PropTypes.string,
  }).isRequired,
  singleEvent: React.PropTypes.shape({
    title: React.PropTypes.string,
    description: React.PropTypes.string,
    price: React.PropTypes.string,
    date: React.PropTypes.string,
    quota: React.PropTypes.array,
  }),
};

export default SingleEvent;
<|endoftext|>


<commit_before>const base = require( './base.js' );

module.exports = Object.assign( {}, base, {
    list: [
        '300',
        '300i',
        'aegis',
        'anderson',
        'anvil',
        'arrow',
        'aurora',
        'avacado',
        'avenger',
        'ayy',
        'banu',
        'bbangry',
        'bbcreep',
        'bbhappy',
        'bbsad',
        'bbsuprised',
        'bbyelling',
        'bengal',
        'bishop',
        'blueguy',
        'bmm',
        'buccaneer',
        'carrack',
        'classicoutlaw',
        'connie',
        'cutlass',
        'defender',
        'dragonfly',
        'drake',
        'freelancer',
        'genericgoofy',
        'hamill',
        'hawk1',
        'herald',
        'herald2',
        'hornet',
        'm50',
        'misc',
        'mitra',
        'mrhasgaha',
        'mustang',
        'nomad',
        'oldman',
        'onionknight',
        'onionknight2',
        'org1',
        'org10',
        'org2',
        'org3',
        'org4',
        'org5',
        'org6',
        'org7',
        'org8',
        'org9',
        'origin',
        'outland',
        'outlaw1',
        'razor',
        'reliant',
        'rsi',
        'runtillyoupuke',
        'sabre',
        'sabre2',
        'santokyai',
        'scout',
        'scythe',
        'solder1',
        'soldier1',
        'tali',
        'thug',
        'tumbril',
        'twitch',
        'vanduul',
        'worm',
        'youtube',
    ],
    type: 'author_flair_css_class',
} );
<commit_msg>Add flair<commit_after>const base = require( './base.js' );

module.exports = Object.assign( {}, base, {
    list: [
        '300',
        '300i',
        'aegis',
        'anderson',
        'anvil',
        'arrow',
        'aurora',
        'avacado',
        'avenger',
        'ayy',
        'banu',
        'bbangry',
        'bbcreep',
        'bbhappy',
        'bbsad',
        'bbsuprised',
        'bbyelling',
        'bengal',
        'bishop',
        'blueguy',
        'bmm',
        'buccaneer',
        'carrack',
        'classicoutlaw',
        'connie',
        'cutlass',
        'defender',
        'dragonfly',
        'drake',
        'freelancer',
        'genericgoofy',
        'hamill',
        'hawk1',
        'hawk2',
        'herald',
        'herald2',
        'hornet',
        'm50',
        'misc',
        'mitra',
        'mrhasgaha',
        'mustang',
        'nomad',
        'oldman',
        'onionknight',
        'onionknight2',
        'org1',
        'org10',
        'org2',
        'org3',
        'org4',
        'org5',
        'org6',
        'org7',
        'org8',
        'org9',
        'origin',
        'outland',
        'outlaw1',
        'razor',
        'reliant',
        'rsi',
        'runtillyoupuke',
        'sabre',
        'sabre2',
        'santokyai',
        'scout',
        'scythe',
        'solder1',
        'soldier1',
        'tali',
        'thug',
        'tumbril',
        'twitch',
        'vanduul',
        'worm',
        'youtube',
    ],
    type: 'author_flair_css_class',
} );
<|endoftext|>


<commit_before>const Board = require('./board')

const helper = require('./helper')
const setting = require('./setting')
const sgf = require('./sgf')

exports.new = function() {
    return {
        id: helper.getId(),
        nodes: [],
        subtrees: [],
        current: null,
        parent: null,
        collapsed: false
    }
}

exports.clone = function(tree, parent = null) {
    let c = {
        id: tree.id,
        nodes: [],
        subtrees: [],
        current: tree.current,
        parent: parent,
        collapsed: tree.collapsed
    }

    tree.nodes.forEach(node => {
        let cn = {}

        for (let key in node) {
            if (key == 'board') continue

            if (Object.prototype.toString.call(node[key]) == '[object Array]') {
                cn[key] = []

                for (let i = 0; i < node[key].length; i++) {
                    cn[key].push(node[key][i])
                }
            } else {
                cn[key] = node[key]
            }
        }

        c.nodes.push(cn)
    })

    tree.subtrees.forEach(subtree => {
        c.subtrees.push(exports.clone(subtree, c))
    })

    return c
}

exports.getRoot = function(tree) {
    while (tree.parent != null) tree = tree.parent
    return tree
}

exports.getPlayerName = function(tree, sign, fallback = '') {
    tree = exports.getRoot(tree)
    let color = sign > 0 ? 'B' : 'W'

    if (tree.nodes.length == 0) return fallback

    let result = ''
    if (('P' + color) in tree.nodes[0]) result = tree.nodes[0]['P' + color][0]
    else if ((color + 'T') in tree.nodes[0]) result = tree.nodes[0][color + 'T'][0]

    return result.trim() == '' ? fallback : result
}

exports.getHeight = function(tree) {
    let height = 0

    tree.subtrees.forEach(subtree => {
        height = Math.max(exports.getHeight(subtree), height)
    })

    return height + tree.nodes.length
}

exports.getCurrentHeight = function(tree) {
    let height = tree.nodes.length

    if (tree.current != null)
        height += exports.getCurrentHeight(tree.subtrees[tree.current])

    return height
}

exports.getLevel = function(tree, index) {
    return index + (tree.parent ? exports.getLevel(tree.parent, tree.parent.nodes.length) : 0)
}

exports.getSection = function(tree, level) {
    if (level < 0) return []
    if (level < tree.nodes.length) return [[tree, level]]

    let sections = []

    tree.subtrees.forEach(subtree => {
        sections = sections.concat(exports.getSection(subtree, level - tree.nodes.length))
    })

    return sections
}

exports.getMatrixDict = function(tree, matrix, dict = {}, xshift = 0, yshift = 0) {
    if (!matrix) matrix = Array.apply(null, new Array(exports.getHeight(tree))).map(() => [])

    let hasCollisions = true
    while (hasCollisions) {
        hasCollisions = false

        for (let y = 0; y < Math.min(tree.nodes.length + 1, matrix.length - yshift); y++) {
            if (xshift >= matrix[yshift + y].length - Math.max(0, y + 1 - tree.nodes.length)) continue

            hasCollisions = true
            xshift++
            break
        }
    }

    for (let y = 0; y < tree.nodes.length; y++) {
        while (xshift >= matrix[yshift + y].length) {
            matrix[yshift + y].push(null)
        }

        matrix[yshift + y][xshift] = [tree, y]
        dict[tree.id + '-' + y] = [xshift, yshift + y]
    }

    if (!tree.collapsed) {
        for (let k = 0; k < tree.subtrees.length; k++) {
            let subtree = tree.subtrees[k]
            exports.getMatrixDict(subtree, matrix, dict, xshift, yshift + tree.nodes.length)
        }
    }

    return [matrix, dict]
}

exports.navigate = function(tree, index, step) {
    if (index + step >= 0 && index + step < tree.nodes.length) {
        return [tree, index + step]
    } else if (index + step < 0 && tree.parent != null) {
        let prev = tree.parent
        let newstep = index + step + 1

        return exports.navigate(prev, prev.nodes.length - 1, newstep)
    } else if (index + step >= tree.nodes.length && tree.current != null) {
        let next = tree.subtrees[tree.current]
        let newstep = index + step - tree.nodes.length

        return exports.navigate(next, 0, newstep)
    }

    return null
}

exports.makeHorizontalNavigator = function(tree, index) {
    let root = exports.getRoot(tree)
    let level = exports.getLevel(tree, index, root)
    let sections = exports.getSection(root, level)
    let j = sections.map(x => x[0]).indexOf(tree)

    return {
        navigate(step) {
            if (j + step >= 0 && j + step < sections.length) {
                j = j + step
            } else if (j + step >= sections.length) {
                step = j + step - sections.length
                sections = exports.getSection(root, ++level)
                j = 0
                if (sections.length != 0) this.navigate(step)
            } else if (j + step < 0) {
                step = j + step + 1
                sections = exports.getSection(root, --level)
                j = sections.length - 1
                if (sections.length != 0) this.navigate(step)
            }
        },
        value() {
            return j < sections.length && j >= 0 ? sections[j] : null
        },
        next() {
            this.navigate(1)
            return this.value()
        },
        prev() {
            this.navigate(-1)
            return this.value()
        }
    }
}

exports.splitTree = function(tree, index) {
    if (index < 0 || index >= tree.nodes.length - 1) return tree

    let newnodes = tree.nodes.slice(0, index + 1)
    tree.nodes = tree.nodes.slice(index + 1)

    let newtree = exports.new()
    newtree.nodes = newnodes
    newtree.subtrees = [tree]
    newtree.parent = tree.parent
    newtree.current = 0
    tree.parent = newtree

    if (newtree.parent)
        newtree.parent.subtrees[newtree.parent.subtrees.indexOf(tree)] = newtree

    return newtree
}

exports.reduceTree = function(tree) {
    if (tree.subtrees.length != 1) return tree

    tree.nodes = tree.nodes.concat(tree.subtrees[0].nodes)
    tree.current = tree.subtrees[0].current
    tree.subtrees = tree.subtrees[0].subtrees

    tree.subtrees.forEach(subtree => {
        subtree.parent = tree
    })

    return tree
}

exports.getMatrixWidth = function(y, matrix) {
    let keys = Object.keys(new Int8Array(10))
        .map(i => parseFloat(i) + y - 4)
        .filter(i => i >= 0 && i < matrix.length)

    let padding = Math.min(...keys.map(i => {
        for (let j = 0; j < matrix[i].length; j++)
            if (matrix[i][j] != null) return j
        return 0
    }))

    let width = Math.max(...keys.map(i => matrix[i].length)) - padding

    return [width, padding]
}

exports.onCurrentTrack = function(tree) {
    return !tree.parent
    || tree.parent.subtrees[tree.parent.current] == tree
    && exports.onCurrentTrack(tree.parent)
}

exports.onMainTrack = function(tree) {
    return !tree.parent
    || tree.parent.subtrees[0] == tree
    && exports.onMainTrack(tree.parent)
}

exports.matrixdict2graph = function(matrixdict) {
    let matrix = matrixdict[0]
    let dict = matrixdict[1]
    let graph = { nodes: [], edges: [] }
    let currentTrack = []
    let notCurrentTrack = []
    let width = Math.max(...matrix.map(x => x.length))
    let gridSize = setting.get('graph.grid_size')

    for (let y = 0; y < matrix.length; y++) {
        for (let x = 0; x < width; x++) {
            if (!matrix[y][x]) continue

            let tree = matrix[y][x][0]
            let index = matrix[y][x][1]
            let id = tree.id + '-' + index
            let commentproperties = setting.get('sgf.comment_properties')
            let node = {
                id: id,
                x: x * gridSize,
                y: y * gridSize,
                size: setting.get('graph.node_size'),
                data: matrix[y][x],
                originalColor: setting.get('graph.node_color')
            }

            // Show passes as squares

            if ('B' in tree.nodes[index] && tree.nodes[index].B[0] == ''
            || 'W' in tree.nodes[index] && tree.nodes[index].W[0] == '') {
                node.type = 'square'
                node.size++
            }

            // Show non-moves as diamonds

            if (!('B' in tree.nodes[index] || 'W' in tree.nodes[index])) {
                node.type = 'diamond'
                node.size++
            }

            // Set color

            if (commentproperties.some(x => x in tree.nodes[index]))
                node.originalColor = setting.get('graph.node_comment_color')
            if ('HO' in tree.nodes[index])
                node.originalColor = setting.get('graph.node_bookmark_color')

            if (currentTrack.indexOf(tree.id) != -1) {
                node.color = node.originalColor
            } else if (notCurrentTrack.indexOf(tree.id) == -1) {
                if (exports.onCurrentTrack(tree)) {
                    currentTrack.push(tree.id)
                    node.color = node.originalColor
                } else {
                    notCurrentTrack.push(tree.id)
                }
            }

            if (tree.collapsed && tree.subtrees.length > 0 && index == tree.nodes.length - 1)
                node.color = node.originalColor = setting.get('graph.node_collapsed_color')

            graph.nodes.push(node)

            // Add helper nodes & edges

            let prev = exports.navigate(tree, index, -1)
            if (!prev) continue
            let prevId = prev[0].id + '-' + prev[1]
            let prevPos = dict[prevId]

            if (prevPos[0] != x) {
                graph.nodes.push({
                    id: id + '-h',
                    x: (x - 1) * gridSize,
                    y: (y - 1) * gridSize,
                    size: 0
                })

                graph.edges.push({
                    id: id + '-e1',
                    source: id,
                    target: id + '-h'
                })

                graph.edges.push({
                    id: id + '-e2',
                    source: id + '-h',
                    target: prevId
                })
            } else {
                graph.edges.push({
                    id: id + '-e1',
                    source: id,
                    target: prevId
                })
            }
        }
    }

    return graph
}

exports.addBoard = function(tree, index = 0, baseboard = null) {
    if (index >= tree.nodes.length) return tree

    let node = tree.nodes[index]
    let vertex = null
    let board = null

    // Get base board

    if (!baseboard) {
        let prev = exports.navigate(tree, index, -1)

        if (!prev) {
            let size = [19, 19]

            if ('SZ' in node) {
                size = node.SZ[0]

                if (size.indexOf(':') >= 0) size = size.split(':')
                else size = [size, size]

                size = size.map(x => +x)
            }

            baseboard = new Board(...size)
        } else {
            let prevNode = prev[0].nodes[prev[1]]

            if (!prevNode.board) exports.addBoard(...prev)
            baseboard = prevNode.board
        }
    }

    // Make move

    if ('B' in node) {
        vertex = sgf.point2vertex(node.B[0])
        board = baseboard.makeMove(1, vertex)
    } else if ('W' in node) {
        vertex = sgf.point2vertex(node.W[0])
        board = baseboard.makeMove(-1, vertex)
    }

    if (!board) board = baseboard.clone()

    // Add markup

    let ids = ['AW', 'AE', 'AB']

    for (let i = 0; i < ids.length; i++) {
        if (!(ids[i] in node)) continue

        node[ids[i]].forEach(value => {
            sgf.compressed2list(value).forEach(vertex => {
                board.arrangement[vertex] = i - 1
            })
        })
    }

    if (vertex != null) {
        board.markups[vertex] = ['point', '']
    }

    ids = ['CR', 'MA', 'SQ', 'TR']
    let classes = ['circle', 'cross', 'square', 'triangle']

    for (let i = 0; i < ids.length; i++) {
        if (!(ids[i] in node)) continue

        node[ids[i]].forEach(value => {
            sgf.compressed2list(value).forEach(vertex => {
                board.markups[vertex] = [classes[i], '']
            })
        })
    }

    if ('LB' in node) {
        node.LB.forEach(composed => {
            let sep = composed.indexOf(':')
            let point = composed.slice(0, sep)
            let label = composed.slice(sep + 1).replace(/\s+/, ' ')
            board.markups[sgf.point2vertex(point)] = ['label', label]
        })
    }

    ;['AR', 'LN'].filter(type => type in node).forEach(type => {
        node[type].forEach(composed => {
            let sep = composed.indexOf(':')
            let p1 = composed.slice(0, sep)
            let p2 = composed.slice(sep + 1)
            board.lines.push([sgf.point2vertex(p1), sgf.point2vertex(p2), type == 'AR'])
        })
    })

    node.board = board

    // Add variation overlays

    let addOverlay = (node, type) => {
        let v, sign

        if ('B' in node) {
            v = sgf.point2vertex(node.B[0])
            sign = 1
        } else if ('W' in node) {
            v = sgf.point2vertex(node.W[0])
            sign = -1
        } else {
            return
        }

        if (!board.hasVertex(v)) return
        board.ghosts.push([v, sign, type])
    }

    if (index == 0 && tree.parent) {
        tree.parent.subtrees.forEach(subtree => {
            if (subtree.nodes.length == 0) return
            addOverlay(subtree.nodes[0], 'sibling')
        })
    }

    if (index == tree.nodes.length - 1) {
        tree.subtrees.forEach(subtree => {
            if (subtree.nodes.length == 0) return
            addOverlay(subtree.nodes[0], 'child')
        })
    } else if (index < tree.nodes.length - 1) {
        addOverlay(tree.nodes[index + 1], 'child')
    }

    return tree
}

exports.getJson = function(tree) {
    return JSON.stringify(tree, (name, val) => {
        let list = ['id', 'board', 'parent', 'collapsed', 'current']
        return list.indexOf(name) >= 0 ? undefined : val
    })
}

exports.fromJson = function(json) {
    let addInformation = tree => {
        tree.id = helper.getId()
        tree.collapsed = false

        if (tree.subtrees.length > 0) tree.current = 0

        for (let i = 0; i < tree.subtrees.length; i++) {
            tree.subtrees[i].parent = tree
            addInformation(tree.subtrees[i])
        }

        return tree
    }

    let tree = JSON.parse(json)
    tree.parent = null
    return addInformation(tree)
}

exports.getHash = function(tree) {
    let sgf = require('./sgf')
    return helper.hash(sgf.stringify(tree))
}
<commit_msg>Fix declaring already declared variable<commit_after>const Board = require('./board')

const helper = require('./helper')
const setting = require('./setting')
const sgf = require('./sgf')

exports.new = function() {
    return {
        id: helper.getId(),
        nodes: [],
        subtrees: [],
        current: null,
        parent: null,
        collapsed: false
    }
}

exports.clone = function(tree, parent = null) {
    let c = {
        id: tree.id,
        nodes: [],
        subtrees: [],
        current: tree.current,
        parent: parent,
        collapsed: tree.collapsed
    }

    tree.nodes.forEach(node => {
        let cn = {}

        for (let key in node) {
            if (key == 'board') continue

            if (Object.prototype.toString.call(node[key]) == '[object Array]') {
                cn[key] = []

                for (let i = 0; i < node[key].length; i++) {
                    cn[key].push(node[key][i])
                }
            } else {
                cn[key] = node[key]
            }
        }

        c.nodes.push(cn)
    })

    tree.subtrees.forEach(subtree => {
        c.subtrees.push(exports.clone(subtree, c))
    })

    return c
}

exports.getRoot = function(tree) {
    while (tree.parent != null) tree = tree.parent
    return tree
}

exports.getPlayerName = function(tree, sign, fallback = '') {
    tree = exports.getRoot(tree)
    let color = sign > 0 ? 'B' : 'W'

    if (tree.nodes.length == 0) return fallback

    let result = ''
    if (('P' + color) in tree.nodes[0]) result = tree.nodes[0]['P' + color][0]
    else if ((color + 'T') in tree.nodes[0]) result = tree.nodes[0][color + 'T'][0]

    return result.trim() == '' ? fallback : result
}

exports.getHeight = function(tree) {
    let height = 0

    tree.subtrees.forEach(subtree => {
        height = Math.max(exports.getHeight(subtree), height)
    })

    return height + tree.nodes.length
}

exports.getCurrentHeight = function(tree) {
    let height = tree.nodes.length

    if (tree.current != null)
        height += exports.getCurrentHeight(tree.subtrees[tree.current])

    return height
}

exports.getLevel = function(tree, index) {
    return index + (tree.parent ? exports.getLevel(tree.parent, tree.parent.nodes.length) : 0)
}

exports.getSection = function(tree, level) {
    if (level < 0) return []
    if (level < tree.nodes.length) return [[tree, level]]

    let sections = []

    tree.subtrees.forEach(subtree => {
        sections = sections.concat(exports.getSection(subtree, level - tree.nodes.length))
    })

    return sections
}

exports.getMatrixDict = function(tree, matrix, dict = {}, xshift = 0, yshift = 0) {
    if (!matrix) matrix = Array.apply(null, new Array(exports.getHeight(tree))).map(() => [])

    let hasCollisions = true
    while (hasCollisions) {
        hasCollisions = false

        for (let y = 0; y < Math.min(tree.nodes.length + 1, matrix.length - yshift); y++) {
            if (xshift >= matrix[yshift + y].length - Math.max(0, y + 1 - tree.nodes.length)) continue

            hasCollisions = true
            xshift++
            break
        }
    }

    for (let y = 0; y < tree.nodes.length; y++) {
        while (xshift >= matrix[yshift + y].length) {
            matrix[yshift + y].push(null)
        }

        matrix[yshift + y][xshift] = [tree, y]
        dict[tree.id + '-' + y] = [xshift, yshift + y]
    }

    if (!tree.collapsed) {
        for (let k = 0; k < tree.subtrees.length; k++) {
            let subtree = tree.subtrees[k]
            exports.getMatrixDict(subtree, matrix, dict, xshift, yshift + tree.nodes.length)
        }
    }

    return [matrix, dict]
}

exports.navigate = function(tree, index, step) {
    if (index + step >= 0 && index + step < tree.nodes.length) {
        return [tree, index + step]
    } else if (index + step < 0 && tree.parent != null) {
        let prev = tree.parent
        let newstep = index + step + 1

        return exports.navigate(prev, prev.nodes.length - 1, newstep)
    } else if (index + step >= tree.nodes.length && tree.current != null) {
        let next = tree.subtrees[tree.current]
        let newstep = index + step - tree.nodes.length

        return exports.navigate(next, 0, newstep)
    }

    return null
}

exports.makeHorizontalNavigator = function(tree, index) {
    let root = exports.getRoot(tree)
    let level = exports.getLevel(tree, index, root)
    let sections = exports.getSection(root, level)
    let j = sections.map(x => x[0]).indexOf(tree)

    return {
        navigate(step) {
            if (j + step >= 0 && j + step < sections.length) {
                j = j + step
            } else if (j + step >= sections.length) {
                step = j + step - sections.length
                sections = exports.getSection(root, ++level)
                j = 0
                if (sections.length != 0) this.navigate(step)
            } else if (j + step < 0) {
                step = j + step + 1
                sections = exports.getSection(root, --level)
                j = sections.length - 1
                if (sections.length != 0) this.navigate(step)
            }
        },
        value() {
            return j < sections.length && j >= 0 ? sections[j] : null
        },
        next() {
            this.navigate(1)
            return this.value()
        },
        prev() {
            this.navigate(-1)
            return this.value()
        }
    }
}

exports.splitTree = function(tree, index) {
    if (index < 0 || index >= tree.nodes.length - 1) return tree

    let newnodes = tree.nodes.slice(0, index + 1)
    tree.nodes = tree.nodes.slice(index + 1)

    let newtree = exports.new()
    newtree.nodes = newnodes
    newtree.subtrees = [tree]
    newtree.parent = tree.parent
    newtree.current = 0
    tree.parent = newtree

    if (newtree.parent)
        newtree.parent.subtrees[newtree.parent.subtrees.indexOf(tree)] = newtree

    return newtree
}

exports.reduceTree = function(tree) {
    if (tree.subtrees.length != 1) return tree

    tree.nodes = tree.nodes.concat(tree.subtrees[0].nodes)
    tree.current = tree.subtrees[0].current
    tree.subtrees = tree.subtrees[0].subtrees

    tree.subtrees.forEach(subtree => {
        subtree.parent = tree
    })

    return tree
}

exports.getMatrixWidth = function(y, matrix) {
    let keys = Object.keys(new Int8Array(10))
        .map(i => parseFloat(i) + y - 4)
        .filter(i => i >= 0 && i < matrix.length)

    let padding = Math.min(...keys.map(i => {
        for (let j = 0; j < matrix[i].length; j++)
            if (matrix[i][j] != null) return j
        return 0
    }))

    let width = Math.max(...keys.map(i => matrix[i].length)) - padding

    return [width, padding]
}

exports.onCurrentTrack = function(tree) {
    return !tree.parent
    || tree.parent.subtrees[tree.parent.current] == tree
    && exports.onCurrentTrack(tree.parent)
}

exports.onMainTrack = function(tree) {
    return !tree.parent
    || tree.parent.subtrees[0] == tree
    && exports.onMainTrack(tree.parent)
}

exports.matrixdict2graph = function(matrixdict) {
    let matrix = matrixdict[0]
    let dict = matrixdict[1]
    let graph = { nodes: [], edges: [] }
    let currentTrack = []
    let notCurrentTrack = []
    let width = Math.max(...matrix.map(x => x.length))
    let gridSize = setting.get('graph.grid_size')

    for (let y = 0; y < matrix.length; y++) {
        for (let x = 0; x < width; x++) {
            if (!matrix[y][x]) continue

            let tree = matrix[y][x][0]
            let index = matrix[y][x][1]
            let id = tree.id + '-' + index
            let commentproperties = setting.get('sgf.comment_properties')
            let node = {
                id: id,
                x: x * gridSize,
                y: y * gridSize,
                size: setting.get('graph.node_size'),
                data: matrix[y][x],
                originalColor: setting.get('graph.node_color')
            }

            // Show passes as squares

            if ('B' in tree.nodes[index] && tree.nodes[index].B[0] == ''
            || 'W' in tree.nodes[index] && tree.nodes[index].W[0] == '') {
                node.type = 'square'
                node.size++
            }

            // Show non-moves as diamonds

            if (!('B' in tree.nodes[index] || 'W' in tree.nodes[index])) {
                node.type = 'diamond'
                node.size++
            }

            // Set color

            if (commentproperties.some(x => x in tree.nodes[index]))
                node.originalColor = setting.get('graph.node_comment_color')
            if ('HO' in tree.nodes[index])
                node.originalColor = setting.get('graph.node_bookmark_color')

            if (currentTrack.indexOf(tree.id) != -1) {
                node.color = node.originalColor
            } else if (notCurrentTrack.indexOf(tree.id) == -1) {
                if (exports.onCurrentTrack(tree)) {
                    currentTrack.push(tree.id)
                    node.color = node.originalColor
                } else {
                    notCurrentTrack.push(tree.id)
                }
            }

            if (tree.collapsed && tree.subtrees.length > 0 && index == tree.nodes.length - 1)
                node.color = node.originalColor = setting.get('graph.node_collapsed_color')

            graph.nodes.push(node)

            // Add helper nodes & edges

            let prev = exports.navigate(tree, index, -1)
            if (!prev) continue
            let prevId = prev[0].id + '-' + prev[1]
            let prevPos = dict[prevId]

            if (prevPos[0] != x) {
                graph.nodes.push({
                    id: id + '-h',
                    x: (x - 1) * gridSize,
                    y: (y - 1) * gridSize,
                    size: 0
                })

                graph.edges.push({
                    id: id + '-e1',
                    source: id,
                    target: id + '-h'
                })

                graph.edges.push({
                    id: id + '-e2',
                    source: id + '-h',
                    target: prevId
                })
            } else {
                graph.edges.push({
                    id: id + '-e1',
                    source: id,
                    target: prevId
                })
            }
        }
    }

    return graph
}

exports.addBoard = function(tree, index = 0, baseboard = null) {
    if (index >= tree.nodes.length) return tree

    let node = tree.nodes[index]
    let vertex = null
    let board = null

    // Get base board

    if (!baseboard) {
        let prev = exports.navigate(tree, index, -1)

        if (!prev) {
            let size = [19, 19]

            if ('SZ' in node) {
                size = node.SZ[0]

                if (size.indexOf(':') >= 0) size = size.split(':')
                else size = [size, size]

                size = size.map(x => +x)
            }

            baseboard = new Board(...size)
        } else {
            let prevNode = prev[0].nodes[prev[1]]

            if (!prevNode.board) exports.addBoard(...prev)
            baseboard = prevNode.board
        }
    }

    // Make move

    if ('B' in node) {
        vertex = sgf.point2vertex(node.B[0])
        board = baseboard.makeMove(1, vertex)
    } else if ('W' in node) {
        vertex = sgf.point2vertex(node.W[0])
        board = baseboard.makeMove(-1, vertex)
    }

    if (!board) board = baseboard.clone()

    // Add markup

    let ids = ['AW', 'AE', 'AB']

    for (let i = 0; i < ids.length; i++) {
        if (!(ids[i] in node)) continue

        node[ids[i]].forEach(value => {
            sgf.compressed2list(value).forEach(vertex => {
                board.arrangement[vertex] = i - 1
            })
        })
    }

    if (vertex != null) {
        board.markups[vertex] = ['point', '']
    }

    ids = ['CR', 'MA', 'SQ', 'TR']
    let classes = ['circle', 'cross', 'square', 'triangle']

    for (let i = 0; i < ids.length; i++) {
        if (!(ids[i] in node)) continue

        node[ids[i]].forEach(value => {
            sgf.compressed2list(value).forEach(vertex => {
                board.markups[vertex] = [classes[i], '']
            })
        })
    }

    if ('LB' in node) {
        node.LB.forEach(composed => {
            let sep = composed.indexOf(':')
            let point = composed.slice(0, sep)
            let label = composed.slice(sep + 1).replace(/\s+/, ' ')
            board.markups[sgf.point2vertex(point)] = ['label', label]
        })
    }

    ;['AR', 'LN'].filter(type => type in node).forEach(type => {
        node[type].forEach(composed => {
            let sep = composed.indexOf(':')
            let p1 = composed.slice(0, sep)
            let p2 = composed.slice(sep + 1)
            board.lines.push([sgf.point2vertex(p1), sgf.point2vertex(p2), type == 'AR'])
        })
    })

    node.board = board

    // Add variation overlays

    let addOverlay = (node, type) => {
        let v, sign

        if ('B' in node) {
            v = sgf.point2vertex(node.B[0])
            sign = 1
        } else if ('W' in node) {
            v = sgf.point2vertex(node.W[0])
            sign = -1
        } else {
            return
        }

        if (!board.hasVertex(v)) return
        board.ghosts.push([v, sign, type])
    }

    if (index == 0 && tree.parent) {
        tree.parent.subtrees.forEach(subtree => {
            if (subtree.nodes.length == 0) return
            addOverlay(subtree.nodes[0], 'sibling')
        })
    }

    if (index == tree.nodes.length - 1) {
        tree.subtrees.forEach(subtree => {
            if (subtree.nodes.length == 0) return
            addOverlay(subtree.nodes[0], 'child')
        })
    } else if (index < tree.nodes.length - 1) {
        addOverlay(tree.nodes[index + 1], 'child')
    }

    return tree
}

exports.getJson = function(tree) {
    return JSON.stringify(tree, (name, val) => {
        let list = ['id', 'board', 'parent', 'collapsed', 'current']
        return list.indexOf(name) >= 0 ? undefined : val
    })
}

exports.fromJson = function(json) {
    let addInformation = tree => {
        tree.id = helper.getId()
        tree.collapsed = false

        if (tree.subtrees.length > 0) tree.current = 0

        for (let i = 0; i < tree.subtrees.length; i++) {
            tree.subtrees[i].parent = tree
            addInformation(tree.subtrees[i])
        }

        return tree
    }

    let tree = JSON.parse(json)
    tree.parent = null
    return addInformation(tree)
}

exports.getHash = function(tree) {
    return helper.hash(sgf.stringify(tree))
}
<|endoftext|>


<commit_before>(function($) {

  var app = $.sammy(function() {
    this.element_selector = '#main';
    this.use(Sammy.Template);
    this.use(Sammy.Session);

    this.before(function() {
      // load the items
      var context = this;
      $.ajax({
        url: 'data/items.js',
        dataType: 'json',
        async: false,
        success: function(items) {
          context.items = items;
        }
      });
    });

    this.get('#/', function(context) {
      context.app.swap('');
      $.each(context.items, function(i, item) {
        context.partial('templates/item.template', {id: i, item: item}, function(rendered) {
          context.$element().append(rendered);
        });
      });
    });

    this.get('#/item/:id', function(context) {
      this.item = this.items[this.params['id']];
      if (!this.item) { return this.notFound(); }
      this.partial('templates/item_detail.template');
    });

    this.post('#/cart', function(context) {
      var item_id = this.params['item_id'];
      // fetch the current cart
      var cart  = this.session('cart', function() {
        return {};
      });
      if (!cart[item_id]) {
        // this item is not yet in our cart
        // initialize its quantity with 0
        cart[item_id] = 0;
      }
      cart[item_id] += parseInt(this.params['quantity']);
      // store the cart
      this.session('cart', cart);
      this.log("The current cart: ", cart);
    });

    this.bind('update-cart', function() {

    });

  });

  $(function() {
    app.run('#/');
  });

})(jQuery);<commit_msg>Added contents for update-cart event<commit_after>(function($) {

  var app = $.sammy(function() {
    this.element_selector = '#main';
    this.use(Sammy.Template);
    this.use(Sammy.Session);

    this.before(function() {
      // load the items
      var context = this;
      $.ajax({
        url: 'data/items.js',
        dataType: 'json',
        async: false,
        success: function(items) {
          context.items = items;
        }
      });
    });

    this.get('#/', function(context) {
      context.app.swap('');
      $.each(context.items, function(i, item) {
        context.partial('templates/item.template', {id: i, item: item}, function(rendered) {
          context.$element().append(rendered);
        });
      });
    });

    this.get('#/item/:id', function(context) {
      this.item = this.items[this.params['id']];
      if (!this.item) { return this.notFound(); }
      this.partial('templates/item_detail.template');
    });

    this.post('#/cart', function(context) {
      var item_id = this.params['item_id'];
      // fetch the current cart
      var cart  = this.session('cart', function() {
        return {};
      });
      if (!cart[item_id]) {
        // this item is not yet in our cart
        // initialize its quantity with 0
        cart[item_id] = 0;
      }
      cart[item_id] += parseInt(this.params['quantity']);
      // store the cart
      this.session('cart', cart);
      this.log("The current cart: ", cart);
    });

    this.bind('update-cart', function() {
      var sum = 0;
      $.each(this.session('cart') || {}, function(id, quantity) {
        sum += quantity;
      });
      $('.cart-info')
          .find('.cart-items').text(sum).end()
          .animate({paddingTop: '30px'})
          .animate({paddingTop: '10px'});
    });

  });

  $(function() {
    app.run('#/');
  });

})(jQuery);<|endoftext|>