<commit_before>/*
* Encoding and decoding diameter messages
*/
<commit_msg>Command codes and base AVPs<commit_after>/*
 * Encoding and decoding diameter messages
 */

/*

  Diameter header
  ===============

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |    Version    |                 Message Length                |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | Command Flags |                  Command Code                 |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                         Application-ID                        |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                      Hop-by-Hop Identifier                    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                      End-to-End Identifier                    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  AVPs ...
  +-+-+-+-+-+-+-+-+-+-+-+-+-

*/

var COMMAND_CODE = {

	ASR: { code: 274, name: 'Abort-Session-Request'	},
	ASA: { code: 274, name: 'Abort-Session-Answer' },
	ACR: { code: 271, name: 'Accounting-Request' },
	ACA: { code: 271, name: 'Accounting-Answer'	},
	CER: { code: 257, name: 'Capabilities-Exchange-Request'	},
	CEA: { code: 257, name: 'Capabilities-Exchange-Answer' },
	DWR: { code: 280, name: 'Device-Watchdog-Request' },
	DWA: { code: 280, name: 'Device-Watchdog-Answer' },
	DPR: { code: 282, name: 'Disconnect-Peer-Request' },
	DPA: { code: 282, name: 'Disconnect-Peer-Answer' },
	RAR: { code: 258, name: 'Re-Auth-Request' },
	RAA: { code: 258, name: 'Re-Auth-Answer' },
	STR: { code: 275, name: 'Session-Termination-Request' },
	STA: { code: 275, name: 'Session-Termination-Answer' }

};

Object.freeze(COMMAND_CODE)

var DiameterMessage = function(commandCode, commandFlags) {

	// "This Version field MUST be set to 1 to indicate Diameter Version 1"

	this.version = 1;

	this.commandCode = commandCode;

	this.commandFlags = commandFlags;

	/*

		Application-ID
		==============

		Diameter common message       0
		Diameter base accounting      3
		Relay                         0xffffffff

		*/

	this.applicationId = 0;

	this.hopByHopId = undefined;

	this.endToEndId = undefined;

	this.avps = [];
}

DiameterMessage.prototype.addAVP = function(avp) {
	this.avps.push(avp);
}

var encodeDiameterMessage = function(diameterMessage) {

}

var decodeDiameterMessage = function(data) {

}

/*

	AVP Header
	==========

	0                   1                   2                   3
	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|                           AVP Code                            |
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|V M P r r r r r|                  AVP Length                   |
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|                        Vendor-ID (opt)                        |
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|    Data ...
	+-+-+-+-+-+-+-+-+

*/

var AVP = function(avpCode, avpFlags, vendorId) {

	this.avpCode = avpCode;

	this.avpFlags = avpFlags;

	this.vendorId = vendorId;

	this.data = undefined;
}

AVP.prototype.setData = function(data) {
	this.data = data;
}

// see 4.2.  Basic AVP Data Formats
var encodeAVP = function(avp) {

}

var decodeAVP = function(data) {

}

// Diameter Base AVPs

var baseAVPs = {
  85: 	{ name:"Acct-Interim-Interval", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  483: 	{ name:"Accounting-Realtime-Required", type: "Enumerated", flags: {M:1, V:0, P:0} },
  50: 	{ name:"Acct-Multi-Session-Id", type: "UTF8String", flags: {M:1, V:0, P:0} },
  485: 	{ name:"Accounting-Record-Number", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  480: 	{ name:"Accounting-Record-Type", type: "Enumerated", flags: {M:1, V:0, P:0} },
  44: 	{ name:"Acct-Session-Id", type: "OctetString", flags: {M:1, V:0, P:0} },
  287: 	{ name:"Accounting-Sub-Session-Id", type: "Unsigned64", flags: {M:1, V:0, P:0} },
  259: 	{ name:"Acct-Application-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  258: 	{ name:"Auth-Application-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  274: 	{ name:"Auth-Request-Type", type: "Enumerated", flags: {M:1, V:0, P:0} },
  291: 	{ name:"Authorization-Lifetime", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  276: 	{ name:"Auth-Grace-Period", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  277: 	{ name:"Auth-Session-State", type: "Enumerated", flags: {M:1, V:0, P:0} },
  285: 	{ name:"Re-Auth-Request-Type", type: "Enumerated", flags: {M:1, V:0, P:0} },
  25: 	{ name:"Class", type: "OctetString", flags: {M:1, V:0, P:0} },
  293: 	{ name:"Destination-Host", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  283: 	{ name:"Destination-Realm", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  273: 	{ name:"Disconnect-Cau", type: "Enumerated", flags: {M:1, V:0, P:0} },
  281: 	{ name:"Error-Message", type: "UTF8String", flags: {M:0,V:0,P:0 }},
  294: 	{ name:"Error-Reporting-Host", type: "DiamIdent", flags: {M:0,V:0,P:0} },
  55: 	{ name:"Event-Timestamp", type: "Time", flags: {M:1, V:0, P:0} },
  297: 	{ name:"Experimental-Result", type: "Grouped", flags: {M:1, V:0, P:0} },
  298: 	{ name:"Experimental-Result-Code", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  279: 	{ name:"Failed-AVP", type: "Grouped", flags: {M:1, V:0, P:0} },
  267: 	{ name:"Firmware-Revision", type: "Unsigned32", flags: {M:0,V:0,P:0} },
  257: 	{ name:"Host-IP-Addres", type: "Address", flags: {M:1, V:0, P:0} },
  299: 	{ name:"Inband-Security-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} }
  272: 	{ name:"Multi-Round-Time-Out", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  264: 	{ name:"Origin-Host", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  296: 	{ name:"Origin-Realm", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  278: 	{ name:"Origin-State-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  269: 	{ name:"Product-Name", type: "UTF8String", flags: {M:0,V:0,P:0 }},
  280: 	{ name:"Proxy-Host", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  284: 	{ name:"Proxy-Info", type: "Grouped", flags: {M:1, V:0, P:0} },
  33: 	{ name:"Proxy-State", type: "OctetString", flags: {M:1, V:0, P:0} },
  292: 	{ name:"Redirect-Host", type: "DiamURI", flags: {M:1, V:0, P:0} },
  261: 	{ name:"Redirect-Host-Usage", type: "Enumerated", flags: {M:1, V:0, P:0} },
  262: 	{ name:"Redirect-Max-Cache-Time", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  268: 	{ name:"Result-Code", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  282: 	{ name:"Route-Record", type: "DiamIdent", flags: {M:1, V:0, P:0} },
  263: 	{ name:"Session-Id", type: "UTF8String", flags: {M:1, V:0, P:0} },
  27: 	{ name:"Session-Timeout", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  270: 	{ name:"Session-Binding", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  271: 	{ name:"Session-Server-Failover", type: "Enumerated", flags: {M:1, V:0, P:0} },
  265: 	{ name:"Supported-Vendor-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  295: 	{ name:"Termination-Cause", type: "Enumerated", flags: {M:1, V:0, P:0} },
  1: 		{ name:"User-Name", type: "UTF8String", flags: {M:1, V:0, P:0} },
  266: 	{ name:"Vendor-Id", type: "Unsigned32", flags: {M:1, V:0, P:0} },
  260: 	{ name:"Vendor-Specific-Application-Id", type: "Grouped", flags: {M:1, V:0, P:0} }
};

var avpAcctInterimInterval = function() { return new AVP(85,baseAVPS[85].flags)};
var avpAccountingRealtimeRequired = function() { return new AVP(483,baseAVPS[483].flags)};
var avpAcctMultiSessionId = function() { return new AVP(50,baseAVPS[50].flags)};
var avpAccountingRecordNumber = function() { return new AVP(485,baseAVPS[485].flags)};
var avpAccountingRecordType = function() { return new AVP(480,baseAVPS[480].flags)};
var avpAcctSessionId = function() { return new AVP(44,baseAVPS[44].flags)};
var avpAccountingSubSessionId = function() { return new AVP(287,baseAVPS[287].flags)};
var avpAcctApplicationId = function() { return new AVP(259,baseAVPS[259].flags)};
var avpAuthApplicationId = function() { return new AVP(258,baseAVPS[258].flags)};
var avpAuthRequestType = function() { return new AVP(274,baseAVPS[274].flags)};
var avpAuthorizationLifetime = function() { return new AVP(291,baseAVPS[291].flags)};
var avpAuthGracePeriod = function() { return new AVP(276,baseAVPS[276].flags)};
var avpAuthSessionState = function() { return new AVP(277,baseAVPS[277].flags)};
var avpReAuthRequestType = function() { return new AVP(285,baseAVPS[285].flags)};
var avpClass = function() { return new AVP(25,baseAVPS[25].flags)};
var avpDestinationHost = function() { return new AVP(293,baseAVPS[293].flags)};
var avpDestinationRealm = function() { return new AVP(283,baseAVPS[283].flags)};
var avpDisconnectCause = function() { return new AVP(273,baseAVPS[273].flags)};
var avpErrorMessage = function() { return new AVP(281,baseAVPS[281].flags)};
var avpErrorReportingHost = function() { return new AVP(294,baseAVPS[294].flags)};
var avpEventTimestamp = function() { return new AVP(55,baseAVPS[55].flags)};
var avpExperimentalResult = function() { return new AVP(297,baseAVPS[297].flags)};
var avpExperimentalResultCode = function() { return new AVP(298,baseAVPS[298].flags)};
var avpFailedAVP = function() { return new AVP(279,baseAVPS[279].flags)};
var avpFirmwareRevision = function() { return new AVP(267,baseAVPS[267].flags)};
var avpHostIPAddres = function() { return new AVP(257,baseAVPS[257].flags)};
var avpInbandSecurityId = function() { return new AVP(299,baseAVPS[299].flags)};
var avpMultiRoundTimeOut = function() { return new AVP(272,baseAVPS[272].flags)};
var avpOriginHost = function() { return new AVP(264,baseAVPS[264].flags)};
var avpOriginRealm = function() { return new AVP(296,baseAVPS[296].flags)};
var avpOriginStateId = function() { return new AVP(278,baseAVPS[278].flags)};
var avpProductName = function() { return new AVP(269,baseAVPS[269].flags)};
var avpProxyHost = function() { return new AVP(280,baseAVPS[280].flags)};
var avpProxyInfo = function() { return new AVP(284,baseAVPS[284].flags)};
var avpProxyState = function() { return new AVP(33,baseAVPS[33].flags)};
var avpRedirectHost = function() { return new AVP(292,baseAVPS[292].flags)};
var avpRedirectHostUsage = function() { return new AVP(261,baseAVPS[261].flags)};
var avpRedirectMaxCacheTime = function() { return new AVP(262,baseAVPS[262].flags)};
var avpResultCode = function() { return new AVP(268,baseAVPS[268].flags)};
var avpRouteRecord = function() { return new AVP(282,baseAVPS[282].flags)};
var avpSessionId = function() { return new AVP(263,baseAVPS[263].flags)};
var avpSessionTimeout = function() { return new AVP(27,baseAVPS[27].flags)};
var avpSessionBinding = function() { return new AVP(270,baseAVPS[270].flags)};
var avpSessionServerFailover = function() { return new AVP(271,baseAVPS[271].flags)};
var avpSupportedVendorId = function() { return new AVP(265,baseAVPS[265].flags)};
var avpTerminationCause = function() { return new AVP(295,baseAVPS[295].flags)};
var avpUserName = function() { return new AVP(1,baseAVPS[1].flags)};
var avpVendorId = function() { return new AVP(266,baseAVPS[266].flags)};
var avpVendorSpecificApplicationId = function() { return new AVP(260,baseAVPS[260].flags)};
/*

*/
<|endoftext|>


<commit_before>'use strict';

import './style.css';
import _ from 'lodash';
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import d3 from 'd3';
import helpers from '../../helpers';

class Chart extends React.Component {

  constructor(props) {
    super(props);
    this.data = [];
    this.state = {
      chartData: props.chartData,
      layerName: props.layerName,
      codgov: props.codgov,
      date: props.date,
      unit: props.unit
    };
  }

  fetchData() {
    const username = this.props.cartodbUser;
    const sql = this.state.chartData.query
      .replace(/\$\{columnName\}/g, this.state.layerName)
      .replace(/\$\{codgov\}/g, this.state.codgov);
    const url = `https:\/\/${username}.cartodb.com/api/v2/sql?q=${sql}`;
    $.getJSON(url, (d) => {
      this.data = d.rows;
      this.clearView();
      this.renderSparkLine(d.rows);
    }).fail((err) => {
      throw err.responseText;
    });
  }

  componentDidUpdate() {
    this.clearView();
    this.fetchData();
  }

  componentDidMount() {
    if (this.state.codgov) {
      this.fetchData();
    }
  }

  render() {
    if (!this.state.codgov) {
      return null;
    }
    return (

    );
  }

  renderSparkLine(data) {
    const oEl = ReactDOM.findDOMNode(this);

    if (!oEl) {
      return;
    }

    const el = oEl.getElementsByClassName('canvas')[0];
    const dateFormat = '%Y';
    const margin = {top: 15, left: 35, right: 20, bottom: 20};
    const width = el.clientWidth;
    const height = el.clientHeight;
    const x = d3.time.scale().range([0, width - margin.left - margin.right]).nice();
    const y = d3.scale.linear().range([height - margin.bottom - margin.top, 0]);
    const unit = this.state.unit;

    // Creating SVG
    const svg = d3.select(el)
      .append('svg')
        .attr('width', width)
        .attr('height', height)
      .append('g')
        .attr('transform', `translate(${margin.left}, ${margin.top})`);

    // Parsing data
    data.forEach((d) => d.date = new Date(d.year, 0, 1));

    // Domain
    x.domain(d3.extent(data, (d) => d.date));
    y.domain([0, d3.max(data, (d) => {
      const nValue = d.nat_average_value || 0;
      const value = d.average_value || 0;
      const max = value > nValue ? value : nValue;
      return max;
    })]);

    // X Axis
    const xAxis = d3.svg.axis()
      .scale(x)
      .orient('bottom')
      .ticks(d3.time.years, 2)
      .outerTickSize(0)
      .innerTickSize(0)
      .tickFormat(d3.time.format(dateFormat));

    svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', `translate(0, ${height - margin.bottom - margin.top})`)
      .call(xAxis);

    // svg.append('text')
    //   .attr('class', 'x label')
    //   .attr('x', width / 2)
    //   .attr('y', height - 17)
    //   .text('years');

    // Y Axis
    const yAxis = d3.svg.axis()
      .scale(y)
      .orient('left')
      .outerTickSize(0)
      .innerTickSize(0)
      .ticks(5);

    svg.append('g')
      .attr('class', 'y axis')
      .call(yAxis);

    if (this.state.unit) {
      svg.append('text')
      .attr('class', 'y label')
      .attr('x', -4)
      .attr('y', 0)
      .text(this.state.unit);
    }

    // Tooltip
    const tooltip = this.tooltip = d3.select('body').append('div')
      .attr('class', 'tooltip')
      .style('opacity', 0);

    function showTooltip (d, nat) {
      const value = (nat) ? d.nat_average_value : d.average_value;
      const tooltipHtml = `${helpers.formatNumber(value, 3)} ${unit}`;
      tooltip
        .html(tooltipHtml)
        .transition().duration(200)
        .style('opacity', 1)
        .style('top', `${d3.event.pageY}px`)
        .style('left', `${d3.event.pageX}px`);
    }

    function hideTooltip () {
      tooltip.style('opacity', 0);
    }

    // Draw line
    const line = d3.svg.line()
      .interpolate('linear')
      .x((d) => x(d.date))
      .y((d) => y(d.average_value));

    svg.append('path')
      .datum(data)
      .attr('class', 'sparkline')
      .attr('d', line);

    svg.selectAll('dot')
        .data(data).enter()
      .append('circle')
        .attr('class', 'focus')
        .attr('cx', (d) => x(d.date))
        .attr('cy', (d) => y(d.average_value || 0))
        .attr('r', 2)
        .on('mouseover', (d) => {
          showTooltip(d, false);
        })
        .on('mouseout', hideTooltip);

    // Draw average line
    if (data[0].nat_average_value) {
      const avgLine = d3.svg.line()
        .interpolate('linear')
        .x((d) => x(d.date))
        .y((d) => y(d.nat_average_value || 0));

      svg.append('path')
          .datum(data)
          .attr('class', 'avg-sparkline')
          .attr('d', avgLine);

      svg.selectAll('avg-dot')
          .data(data).enter()
        .append('circle')
          .attr('class', 'avg-focus')
          .attr('cx', (d) => x(d.date))
          .attr('cy', (d) => y(d.nat_average_value))
          .attr('r', 2)
          .on('mouseover', (d) => {
            showTooltip(d, true);
          })
          .on('mouseout', hideTooltip);
    }

    // Vertical line
    svg.selectAll('avg-line')
      .data(data).enter()
    .append('line')
      .attr('class', 'year-line')
      .attr('x1', (d) => x(d.date))
      .attr('x2', (d) => x(d.date))
      .attr('y1', 0)
      .attr('y2', (d) => {
        return d.year === this.state.date.getFullYear() ? height - margin.bottom - margin.top : 0;
      });

  }

  clearView() {
    const el = ReactDOM.findDOMNode(this);
    if (el) {
      const chartsElement = el.getElementsByClassName('canvas')[0];
      chartsElement.innerHTML = '';
    }
    if (this.tooltip) {
      this.tooltip.style('opacity', 0);
    }
  }

}

Chart.propTypes = {
  cartodbUser: React.PropTypes.string,
  codgov: React.PropTypes.string,
  date: React.PropTypes.object,
  query: React.PropTypes.string
};

export default Chart;
<commit_msg>fixed #28<commit_after>'use strict';

import './style.css';
import _ from 'lodash';
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import d3 from 'd3';
import helpers from '../../helpers';

class Chart extends React.Component {

  constructor(props) {
    super(props);
    this.data = [];
    this.state = {
      chartData: props.chartData,
      layerName: props.layerName,
      codgov: props.codgov,
      date: props.date,
      unit: props.unit
    };
  }

  fetchData() {
    const username = this.props.cartodbUser;
    const sql = this.state.chartData.query
      .replace(/\$\{columnName\}/g, this.state.layerName)
      .replace(/\$\{codgov\}/g, this.state.codgov);
    const url = `https:\/\/${username}.cartodb.com/api/v2/sql?q=${sql}`;
    $.getJSON(url, (d) => {
      this.data = d.rows;
      this.clearView();
      this.renderSparkLine(d.rows);
    }).fail((err) => {
      throw err.responseText;
    });
  }

  componentDidUpdate() {
    this.clearView();
    this.fetchData();
  }

  componentDidMount() {
    if (this.state.codgov) {
      this.fetchData();
    }
  }

  render() {
    if (!this.state.codgov) {
      return null;
    }
    return (

    );
  }

  renderSparkLine(data) {
    const oEl = ReactDOM.findDOMNode(this);

    if (!oEl) {
      return;
    }

    const el = oEl.getElementsByClassName('canvas')[0];
    const dateFormat = '%Y';
    const margin = {top: 15, left: 35, right: 20, bottom: 20};
    const width = el.clientWidth;
    const height = el.clientHeight;
    const x = d3.time.scale().range([0, width - margin.left - margin.right]).nice();
    const y = d3.scale.linear().range([height - margin.bottom - margin.top, 0]);
    const unit = this.state.unit || '';

    // Creating SVG
    const svg = d3.select(el)
      .append('svg')
        .attr('width', width)
        .attr('height', height)
      .append('g')
        .attr('transform', `translate(${margin.left}, ${margin.top})`);

    // Parsing data
    data.forEach((d) => d.date = new Date(d.year, 0, 1));

    // Domain
    x.domain(d3.extent(data, (d) => d.date));
    y.domain([0, d3.max(data, (d) => {
      const nValue = d.nat_average_value || 0;
      const value = d.average_value || 0;
      const max = value > nValue ? value : nValue;
      return max;
    })]);

    // X Axis
    const xAxis = d3.svg.axis()
      .scale(x)
      .orient('bottom')
      .ticks(d3.time.years, 2)
      .outerTickSize(0)
      .innerTickSize(0)
      .tickFormat(d3.time.format(dateFormat));

    svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', `translate(0, ${height - margin.bottom - margin.top})`)
      .call(xAxis);

    // svg.append('text')
    //   .attr('class', 'x label')
    //   .attr('x', width / 2)
    //   .attr('y', height - 17)
    //   .text('years');

    // Y Axis
    const yAxis = d3.svg.axis()
      .scale(y)
      .orient('left')
      .outerTickSize(0)
      .innerTickSize(0)
      .ticks(5);

    svg.append('g')
      .attr('class', 'y axis')
      .call(yAxis);

    if (this.state.unit) {
      svg.append('text')
      .attr('class', 'y label')
      .attr('x', -4)
      .attr('y', 0)
      .text(this.state.unit);
    }

    // Tooltip
    const tooltip = this.tooltip = d3.select('body').append('div')
      .attr('class', 'tooltip')
      .style('opacity', 0);

    function showTooltip (d, nat) {
      const value = (nat) ? d.nat_average_value : d.average_value;
      const tooltipHtml = `${helpers.formatNumber(value, 3)} ${unit}`;
      tooltip
        .html(tooltipHtml)
        .transition().duration(200)
        .style('opacity', 1)
        .style('top', `${d3.event.pageY}px`)
        .style('left', `${d3.event.pageX}px`);
    }

    function hideTooltip () {
      tooltip.style('opacity', 0);
    }

    // Draw line
    const line = d3.svg.line()
      .interpolate('linear')
      .x((d) => x(d.date))
      .y((d) => y(d.average_value));

    svg.append('path')
      .datum(data)
      .attr('class', 'sparkline')
      .attr('d', line);

    svg.selectAll('dot')
        .data(data).enter()
      .append('circle')
        .attr('class', 'focus')
        .attr('cx', (d) => x(d.date))
        .attr('cy', (d) => y(d.average_value || 0))
        .attr('r', 2)
        .on('mouseover', (d) => {
          showTooltip(d, false);
        })
        .on('mouseout', hideTooltip);

    // Draw average line
    if (data[0].nat_average_value) {
      const avgLine = d3.svg.line()
        .interpolate('linear')
        .x((d) => x(d.date))
        .y((d) => y(d.nat_average_value || 0));

      svg.append('path')
          .datum(data)
          .attr('class', 'avg-sparkline')
          .attr('d', avgLine);

      svg.selectAll('avg-dot')
          .data(data).enter()
        .append('circle')
          .attr('class', 'avg-focus')
          .attr('cx', (d) => x(d.date))
          .attr('cy', (d) => y(d.nat_average_value))
          .attr('r', 2)
          .on('mouseover', (d) => {
            showTooltip(d, true);
          })
          .on('mouseout', hideTooltip);
    }

    // Vertical line
    svg.selectAll('avg-line')
      .data(data).enter()
    .append('line')
      .attr('class', 'year-line')
      .attr('x1', (d) => x(d.date))
      .attr('x2', (d) => x(d.date))
      .attr('y1', 0)
      .attr('y2', (d) => {
        return d.year === this.state.date.getFullYear() ? height - margin.bottom - margin.top : 0;
      });

  }

  clearView() {
    const el = ReactDOM.findDOMNode(this);
    if (el) {
      const chartsElement = el.getElementsByClassName('canvas')[0];
      chartsElement.innerHTML = '';
    }
    if (this.tooltip) {
      this.tooltip.style('opacity', 0);
    }
  }

}

Chart.propTypes = {
  cartodbUser: React.PropTypes.string,
  codgov: React.PropTypes.string,
  date: React.PropTypes.object,
  query: React.PropTypes.string
};

export default Chart;
<|endoftext|>


<commit_before>var isArrayLike = require('./isArrayLike')
var kindOf = require('./kindOf')

function base (value) {
  // Base implementation which all other kindOf
  // functions were morphed from and compared to.
  // Does not handle arguments
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  var type = value.constructor.name

  if (type === 'String') return 'string'
  if (type === 'Boolean') return 'boolean'
  if (type === 'Number') return 'number'
  if (type === 'Symbol') return 'symbol'
  if (type === 'Function') return 'function'
  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'
  if (type === 'Buffer') return 'buffer'

  return type.toLowerCase()
}

function kind (value) {
  // Return the constructor name if not a primative, array or function
  // A more performant `kindOf` with cavets. Must test ES6 after upgrade.
  // Does not handle arguments.
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  return objType(value)
}

function objs (value) {
  // a speedy version to obtain common object "types"
  // Does not handle arguments.
  if (typeof value === 'function') return 'function'
  if (Array.isArray(value)) return 'array'
  if (typeof value === 'string') return 'string'

  return objType(value)
}

function safe (value) {
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  return objSafe(value)
}

function objType (value) {
  // this will pick out PlainObjects, regexps, and dates
  // quicker than a toString.call() but marginally slower
  // than the base implementation. Fails on arguments,
  // not really though --> arguments [object]
  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'
  if (type === 'Buffer') return 'buffer'

  return type.toLowerCase()
}

function objSafe (value) {
  if (typeof value.pipe === 'function') return 'stream'
  // Object.create(null) throws an error. Code below
  // prevents this from happening. Handles arguments.
  try {
    var type = value.constructor.name

    if (type === 'Object') {
      return isArrayLike(value)
        ? 'arguments'
        : 'object'
    }

    if (type === 'RegExp') return 'regexp'
    if (type === 'Date') return 'date'
    if (type === 'Buffer') return 'buffer'

    return type.toLowerCase()
  } catch (err) {
    return Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
  }
}

module.exports = kind
module.exports.base = base
module.exports.objs = objs
module.exports.safe = safe
module.exports.Of = kindOf
<commit_msg>update lang/kind -- for ES6<commit_after>var isArrayLike = require('./isArrayLike')
var kindOf = require('./kindOf')

function base (value) {
  // Base implementation which all other kindOf
  // functions were morphed from and compared to.
  // Does not handle arguments
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  var type = value.constructor.name

  if (type === 'String') return 'string'
  if (type === 'Boolean') return 'boolean'
  if (type === 'Number') return 'number'
  if (type === 'Symbol') return 'symbol'
  if (type === 'Function') return 'function'
  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'
  if (type === 'Buffer') return 'buffer'
  if (type === 'Map') return 'map'
  if (type === 'WeakMap') return 'weakmap'
  if (type === 'Set') return 'set'
  if (type === 'WeakSet') return 'weakset'

  return type.toLowerCase()
}

function kind (value) {
  // Return the constructor name if not a primative, array or function
  // A more performant `kindOf` with cavets. Must test ES6 after upgrade.
  // Does not handle arguments.
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  return objType(value)
}

function objs (value) {
  // a speedy version to obtain common object "types"
  // Does not handle arguments.
  if (typeof value === 'function') return 'function'
  if (Array.isArray(value)) return 'array'
  if (typeof value === 'string') return 'string'
    // safety check for kind.objs
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  return objType(value)
}

function safe (value) {
  if (value === null) return 'null'
  if (value === undefined) return 'undefined'

  if (Array.isArray(value)) return 'array'

  if (typeof value === 'string') return 'string'
  if (typeof value === 'boolean') return 'boolean'
  if (typeof value === 'number') return 'number'
  if (typeof value === 'symbol') return 'symbol'
  if (typeof value === 'function') return 'function'

  return objSafe(value)
}

function objType (value) {
  // this will pick out PlainObjects, regexps, and dates
  // quicker than a toString.call() but marginally slower
  // than the base implementation. Fails on arguments,
  // not really though --> arguments [object]
  var type = value.constructor.name

  if (type === 'Object') return 'object'
  if (type === 'RegExp') return 'regexp'
  if (type === 'Date') return 'date'
  if (type === 'Buffer') return 'buffer'
  if (type === 'Map') return 'map'
  if (type === 'Set') return 'set'
  if (type === 'WeakMap') return 'weakmap'
  if (type === 'WeakSet') return 'weakset'

  return type.toLowerCase()
}

function objSafe (value) {
  if (typeof value.pipe === 'function') return 'stream'
  // Object.create(null) throws an error. Code below
  // prevents this from happening. Handles arguments.
  try {
    var type = value.constructor.name

    if (type === 'Object') {
      return isArrayLike(value)
        ? 'arguments'
        : 'object'
    }

    if (type === 'RegExp') return 'regexp'
    if (type === 'Date') return 'date'
    if (type === 'Buffer') return 'buffer'
    if (type === 'Map') return 'map'
    if (type === 'Set') return 'set'
    if (type === 'WeakMap') return 'weakmap'
    if (type === 'WeakSet') return 'weakset'

    return type.toLowerCase()
  } catch (err) {
    return Object.prototype.toString.call(value)
      .replace(/^\[object |\]$/g, '')
      .toLowerCase()
  }
}

module.exports = kind
module.exports.base = base
module.exports.objs = objs
module.exports.safe = safe
module.exports.Of = kindOf
<|endoftext|>


<commit_before><commit_msg>add temperature visualization<commit_after><|endoftext|>


<commit_before>'use strict';
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');

describe('serverless-boilerplate:app', () => {
  beforeEach(() => {
    return helpers.run(path.join(__dirname, '../generators/app'));
  });

  // Validate structure
  it('generate base files', () => {
    assert.file([
      'functions',
      'helpers',
      'templates',
      'tests',
      '.env.yml.example',
      '.gitignore',
      'boilerplate-logo.svg',
      'LICENSE',
      'package.json',
      'README.md',
      'serverless.yml'
    ]);
  });
});
<commit_msg>hotfix - remove repo logo from template<commit_after>'use strict';
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');

describe('serverless-boilerplate:app', () => {
  beforeEach(() => {
    return helpers.run(path.join(__dirname, '../generators/app'));
  });

  // Validate structure
  it('generate base files', () => {
    assert.file([
      'functions',
      'helpers',
      'templates',
      'tests',
      '.env.yml.example',
      '.gitignore',
      'LICENSE',
      'package.json',
      'README.md',
      'serverless.yml'
    ]);
  });
});
<|endoftext|>


<commit_before>/*
Handles the requests by executing stuff and replying to the client. Uses promises to get stuff done.
*/

'use strict';
var util = require('util');
var fs = require('fs');

//const boom = require('boom'), //Boom gives us some predefined http codes and proper responses
  //slideDB = require('../database/slideDatabase'), //Database functions specific for slides
  //co = require('../common');
//pptx2html =
//require('../PPTX2HTML/js/pptx2html');

let pptx2html = require('../PPTX2HTML/js/pptx2html');
//import pptx2html from '../PPTX2HTML/js/pptx2html';

module.exports = {
  //Import uploaded PPTX and transform to HTML via PPTX2HTML  or return ERROR
  //TODO: can I run client-side non ES6 javascript in node.js?
  //pptx2html/js/pptx2html.js uses document.ready / Jquery
  //TODO: find out how use of reveal.js in PPTX2HTML works together with our use of
  // reveal.js in slidewiki-platform frontend work by Huw on slide viewer.
  importPPTX: function(request, reply) {
    //request.log('ImportPPTX', 'ImportPPTX service called');
    //TODO: call PPTX2HTML - test with PTTX2HTML/files/test.pptx
    //pptx2html
    //reply(request.payload.file);
    //request.log('ImportPPTX', 'ImportPPTX service called' + request.payload.file);
    //console.log('ImportPPTX data' + request.payload.file);

//see https://github.com/risis-eu/risis-datasets/blob/master/plugins/upload/handleUpload.js#L99
// for example of reading a superagent request
    //!!!request.body!!!
    //console.log('file sent to service: ' + request.payload.file);
    //console.log('file sent to service: ' + request.body);
    //console.log('file sent to service: ' + request.data);
    //console.log('file sent to service: ' + request.content);
    //console.log('file sent to service: ' + request.content.file);
    //evt.target.files[0]

    //console.log(request.payload.file); //<Buffer 50 4b 03 04
    //console.log(request.payload); //{ file: <Buffer 50 4b 0
    console.log(request.params); // {}
    //console.log('file sent to service: request.payload' + request.payload); [object object]
    //console.log('file sent to service: request.params' + request.params);
    //console.log('file sent to service: request.file' + request.file);

    //we should be abe to read request.files.file.data
    //TODO: try multipart multipart/form-data?
    // SEE RISIS SERVER.JS FOR EXAMPLE
    //console.log('file sent to service: request.files.file.size' + request.files.file.data);
    //console.log('file sent to service: request.params.files.file.size' + request.files.file.size);
    //console.log(util.inspect(request.params, {showHidden: true, depth: 100}));
    console.log(util.inspect(request.payload.file.data, {showHidden: true, depth: 100})); //undefined
    console.log(util.inspect(request.payload.file, {showHidden: true, depth: 100})); ////<Buffer 50 4b 03 04
    console.log(util.inspect(request.payload, {showHidden: true, depth: 100}));//{ file: <Buffer 50 4b 0

    //req.params.name
    //console.log('file sent to service: request.payload.size: ' + request.payload.size);
    //console.log('file sent to service: request.payload.files.file.size' + request.payload.files.file.size);
    //console.log('file sent to service: request.payload.files.file.data' + request.payload.files.file.data);
    //console.log('file sent to service: request.files.file.size' + request.files.file.size);
    //console.log('file sent to service: request.files.file.data' + request.files.file.data);
    //console.log('file sent to service: request.payload[0]' + request.payload[0]);
    //console.log('file sent to service: request.payload.files[0]' + request.payload.files[0]);
    //console.log('file sent to service request.payload.form: ' + request.payload.form);
    //console.log('file sent to service request.payload.data: ' + request.payload.data);
    //console.log('file sent to service request.payload.file: ' + request.payload.file);
    //console.log('file sent to service request.payload.file.data: ' + request.payload.file.data);
        //console.log('file sent to service request.payload.file: ' + request.payload.file);
    //console.log('file sent to service request.payload.File: ' + request.payload.File);
    //console.log('file sent to service request.payload.filename: ' + request.payload.filename);
    //console.log(util.inspect(request.payload, {showHidden: true, depth: 100}));
    //console.log(util.inspect(request.payload.file, {showHidden: true, depth: 100}));
    //console.log(util.inspect(request.payload.files, {showHidden: true, depth: 100}));
    //reply('request.payload: ' + request.payload);
    //console.log('file sent to service: ' + request.payload.file);
    //console.log('file sent to service: ' + request.payload.body);
    //console.log('file sent to service: ' + request.payload.data);
    //console.log('file sent to service: ' + request.payload.content);
    //pptx2html.convert(request.payload.file);
    //let result = pptx2html.convert(request.params);
    //let file = evt.target.files[0];
    //this.props.ImportStore.file = file;

    //let result = pptx2html.convert(request.payload.file);
    //let result = pptx2html.convert(request.body);
    //let result = pptx2html.convert(request.data);
    //let result = pptx2html.convert(request.content);
    //let result = pptx2html.convert(request.payload[0]);
    //console.log(pptx2html.convert(result));
    //console.log(pptx2html.convert(request.payload.file.data));
    //console.log(pptx2html.convert(request.payload.data)); // Uncaught error: cannot read as File: undefined
    //console.log(pptx2html.convert(request.payload)); // Error: Uncaught error: cannot read as File: {"file":{"type":"Buffer","data":[8
    //request.payload.file.data
    //console.log(
    //console.log(fs.readFile(request.payload.file));
    //let test = request.payload.file;
    //console.log(pptx2html.convert(test)); //Error: Uncaught error: cannot read as File: {"type":"Buffer","data":[80,75,3,4,20,0,6,0,8,

    //console.log(pptx2html.convert(request.payload.file[0])); // Uncaught error: cannot read as File: 80
    //console.log(pptx2html.convert(request.payload.files[0])); Cannot read property '0' of undefined
    //console.log(pptx2html.convert(request.payload.file.files[0])); Uncaught error: Cannot read property '0' of undefined
    //console.log(pptx2html.convert(request.payload.files.files)); Cannot read property 'files' of undefined

    var saveTo = './testingtests.pptx';
    var fileStream = fs.createWriteStream(saveTo);
    //fileStream.write(request.payload.file.data);
    fileStream.write(request.payload.file);
    fileStream.end();
    fileStream.on('error', function (err) {
        reply("error in upload!");
        console.log("error", err);
    });
    fileStream.on('finish', function (res) {
        reply("upload completed!");
        console.log("upload completed");
});

    //console.log(result);

    //console.log(pptx2html.convert(request.params));

    //TODO: give HTML ouput of PPTX2HTML
    //reply('importservice result = HTML from PPTX import');
    //reply(result);

    //slideDB.get(encodeURIComponent(request.params.id)).then((slide) => {
    //  if (co.isEmpty(slide))
    //    reply(boom.notFound());
    //  else
    //    reply(co.rewriteID(slide));
    //}).catch((error) => {
    //  request.log('error', error);
    //  reply(boom.badImplementation());
    //});
  }
  /*
  //Get Slide from database or return NOT FOUND
  getSlide: function(request, reply) {
    slideDB.get(encodeURIComponent(request.params.id)).then((slide) => {
      if (co.isEmpty(slide))
        reply(boom.notFound());
      else
        reply(co.rewriteID(slide));
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Create Slide with new id and payload or return INTERNAL_SERVER_ERROR
  newSlide: function(request, reply) {
    slideDB.insert(request.payload).then((inserted) => {
      if (co.isEmpty(inserted.ops[0]))
        throw inserted;
      else
        reply(co.rewriteID(inserted.ops[0]));
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Update Slide with id id and payload or return INTERNAL_SERVER_ERROR
  replaceSlide: function(request, reply) {
    slideDB.replace(encodeURIComponent(request.params.id), request.payload).then((replaced) => {
      if (co.isEmpty(replaced.value))
        throw replaced;
      else
        reply(replaced.value);
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },
  */
};
<commit_msg>SWIK-111 and SWIK-100 - Corrected some lint issues<commit_after>/*
Handles the requests by executing stuff and replying to the client. Uses promises to get stuff done.
*/

'use strict';
let util = require('util');
let fs = require('fs');

//const boom = require('boom'), //Boom gives us some predefined http codes and proper responses
  //slideDB = require('../database/slideDatabase'), //Database functions specific for slides
  //co = require('../common');
//pptx2html =
//require('../PPTX2HTML/js/pptx2html');

let pptx2html = require('../PPTX2HTML/js/pptx2html');
//import pptx2html from '../PPTX2HTML/js/pptx2html';

module.exports = {
  //Import uploaded PPTX and transform to HTML via PPTX2HTML  or return ERROR
  //TODO: can I run client-side non ES6 javascript in node.js?
  //pptx2html/js/pptx2html.js uses document.ready / Jquery
  //TODO: find out how use of reveal.js in PPTX2HTML works together with our use of
  // reveal.js in slidewiki-platform frontend work by Huw on slide viewer.
  importPPTX: function(request, reply) {
    //request.log('ImportPPTX', 'ImportPPTX service called');
    //TODO: call PPTX2HTML - test with PTTX2HTML/files/test.pptx
    //pptx2html
    //reply(request.payload.file);
    //request.log('ImportPPTX', 'ImportPPTX service called' + request.payload.file);
    //console.log('ImportPPTX data' + request.payload.file);

//see https://github.com/risis-eu/risis-datasets/blob/master/plugins/upload/handleUpload.js#L99
// for example of reading a superagent request
    //!!!request.body!!!
    //console.log('file sent to service: ' + request.payload.file);
    //console.log('file sent to service: ' + request.body);
    //console.log('file sent to service: ' + request.data);
    //console.log('file sent to service: ' + request.content);
    //console.log('file sent to service: ' + request.content.file);
    //evt.target.files[0]

    //console.log(request.payload.file); //<Buffer 50 4b 03 04
    //console.log(request.payload); //{ file: <Buffer 50 4b 0
    console.log(request.params); // {}
    //console.log('file sent to service: request.payload' + request.payload); [object object]
    //console.log('file sent to service: request.params' + request.params);
    //console.log('file sent to service: request.file' + request.file);

    //we should be abe to read request.files.file.data
    //TODO: try multipart multipart/form-data?
    // SEE RISIS SERVER.JS FOR EXAMPLE
    //console.log('file sent to service: request.files.file.size' + request.files.file.data);
    //console.log('file sent to service: request.params.files.file.size' + request.files.file.size);
    //console.log(util.inspect(request.params, {showHidden: true, depth: 100}));
    console.log(util.inspect(request.payload.file.data, {showHidden: true, depth: 100})); //undefined
    console.log(util.inspect(request.payload.file, {showHidden: true, depth: 100})); ////<Buffer 50 4b 03 04
    console.log(util.inspect(request.payload, {showHidden: true, depth: 100}));//{ file: <Buffer 50 4b 0

    //req.params.name
    //console.log('file sent to service: request.payload.size: ' + request.payload.size);
    //console.log('file sent to service: request.payload.files.file.size' + request.payload.files.file.size);
    //console.log('file sent to service: request.payload.files.file.data' + request.payload.files.file.data);
    //console.log('file sent to service: request.files.file.size' + request.files.file.size);
    //console.log('file sent to service: request.files.file.data' + request.files.file.data);
    //console.log('file sent to service: request.payload[0]' + request.payload[0]);
    //console.log('file sent to service: request.payload.files[0]' + request.payload.files[0]);
    //console.log('file sent to service request.payload.form: ' + request.payload.form);
    //console.log('file sent to service request.payload.data: ' + request.payload.data);
    //console.log('file sent to service request.payload.file: ' + request.payload.file);
    //console.log('file sent to service request.payload.file.data: ' + request.payload.file.data);
        //console.log('file sent to service request.payload.file: ' + request.payload.file);
    //console.log('file sent to service request.payload.File: ' + request.payload.File);
    //console.log('file sent to service request.payload.filename: ' + request.payload.filename);
    //console.log(util.inspect(request.payload, {showHidden: true, depth: 100}));
    //console.log(util.inspect(request.payload.file, {showHidden: true, depth: 100}));
    //console.log(util.inspect(request.payload.files, {showHidden: true, depth: 100}));
    //reply('request.payload: ' + request.payload);
    //console.log('file sent to service: ' + request.payload.file);
    //console.log('file sent to service: ' + request.payload.body);
    //console.log('file sent to service: ' + request.payload.data);
    //console.log('file sent to service: ' + request.payload.content);
    //pptx2html.convert(request.payload.file);
    //let result = pptx2html.convert(request.params);
    //let file = evt.target.files[0];
    //this.props.ImportStore.file = file;

    //let result = pptx2html.convert(request.payload.file);
    //let result = pptx2html.convert(request.body);
    //let result = pptx2html.convert(request.data);
    //let result = pptx2html.convert(request.content);
    //let result = pptx2html.convert(request.payload[0]);
    //console.log(pptx2html.convert(result));
    //console.log(pptx2html.convert(request.payload.file.data));
    //console.log(pptx2html.convert(request.payload.data)); // Uncaught error: cannot read as File: undefined
    //console.log(pptx2html.convert(request.payload)); // Error: Uncaught error: cannot read as File: {"file":{"type":"Buffer","data":[8
    //request.payload.file.data
    //console.log(
    //console.log(fs.readFile(request.payload.file));
    //let test = request.payload.file;
    //console.log(pptx2html.convert(test)); //Error: Uncaught error: cannot read as File: {"type":"Buffer","data":[80,75,3,4,20,0,6,0,8,

    //console.log(pptx2html.convert(request.payload.file[0])); // Uncaught error: cannot read as File: 80
    //console.log(pptx2html.convert(request.payload.files[0])); Cannot read property '0' of undefined
    //console.log(pptx2html.convert(request.payload.file.files[0])); Uncaught error: Cannot read property '0' of undefined
    //console.log(pptx2html.convert(request.payload.files.files)); Cannot read property 'files' of undefined

    let saveTo = './testingtests.pptx';
    let fileStream = fs.createWriteStream(saveTo);
    //fileStream.write(request.payload.file.data);
    fileStream.write(request.payload.file);
    fileStream.end();
    fileStream.on('error', (err) => {
      reply('error in upload!');
      console.log('error', err);
    });
    fileStream.on('finish', (res) => {
      reply('upload completed!');
      console.log('upload completed');
    });

    //console.log(result);

    //console.log(pptx2html.convert(request.params));

    //TODO: give HTML ouput of PPTX2HTML
    //reply('importservice result = HTML from PPTX import');
    //reply(result);

    //slideDB.get(encodeURIComponent(request.params.id)).then((slide) => {
    //  if (co.isEmpty(slide))
    //    reply(boom.notFound());
    //  else
    //    reply(co.rewriteID(slide));
    //}).catch((error) => {
    //  request.log('error', error);
    //  reply(boom.badImplementation());
    //});
  }
  /*
  //Get Slide from database or return NOT FOUND
  getSlide: function(request, reply) {
    slideDB.get(encodeURIComponent(request.params.id)).then((slide) => {
      if (co.isEmpty(slide))
        reply(boom.notFound());
      else
        reply(co.rewriteID(slide));
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Create Slide with new id and payload or return INTERNAL_SERVER_ERROR
  newSlide: function(request, reply) {
    slideDB.insert(request.payload).then((inserted) => {
      if (co.isEmpty(inserted.ops[0]))
        throw inserted;
      else
        reply(co.rewriteID(inserted.ops[0]));
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Update Slide with id id and payload or return INTERNAL_SERVER_ERROR
  replaceSlide: function(request, reply) {
    slideDB.replace(encodeURIComponent(request.params.id), request.payload).then((replaced) => {
      if (co.isEmpty(replaced.value))
        throw replaced;
      else
        reply(replaced.value);
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },
  */
};
<|endoftext|>


<commit_before>/*
Handles the requests by executing stuff and replying to the client. Uses promises to get stuff done.
*/

'use strict';

const boom = require('boom'), //Boom gives us some predefined http codes and proper responses
  activitiesDB = require('../database/activitiesDatabase'), //Database functions specific for activities
  co = require('../common');

module.exports = {
  //Get Activity from database or return NOT FOUND
  getActivity: function(request, reply) {
    activitiesDB.get(encodeURIComponent(request.params.id)).then((activity) => {
      if (co.isEmpty(activity))
        reply(boom.notFound());
      else {
        activity.author = authorsMap.get(activity.user_id);//insert author data
        if (activity.author === undefined) {
          activity.author = authorsMap.get('112233445566778899000000');
        }
        reply(co.rewriteID(activity));
      }
    }).catch((error) => {

      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Create Activity with new id and payload or return INTERNAL_SERVER_ERROR
  newActivity: function(request, reply) {
    activitiesDB.insert(request.payload).then((inserted) => {
      //console.log('inserted: ', inserted);
      if (co.isEmpty(inserted.ops) || co.isEmpty(inserted.ops[0]))
        throw inserted;
      else {
        inserted.ops[0].author = authorsMap.get(inserted.ops[0].user_id);//insert author data
        reply(co.rewriteID(inserted.ops[0]));
      }
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Update Activity with id id and payload or return INTERNAL_SERVER_ERROR
  updateActivity: function(request, reply) {
    activitiesDB.replace(encodeURIComponent(request.params.id), request.payload).then((replaced) => {
      //console.log('updated: ', replaced);
      if (co.isEmpty(replaced.value))
        throw replaced;
      else
        reply(replaced.value);
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Delete Activity with id id
  deleteActivity: function(request, reply) {
    activitiesDB.delete(encodeURIComponent(request.payload.id)).then(() =>
      reply({'msg': 'activity is successfully deleted...'})
    ).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Delete Activities with content id id
  deleteActivities: function(request, reply) {
    activitiesDB.deleteAllWithContentID(encodeURIComponent(request.payload.content_id)).then(() =>
      reply({'msg': 'activities are successfully deleted...'})
    ).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Get All Activities from database for the id in the request, limited by the number of documents
  getActivitiesLimited: function(request, reply) {
    activitiesDB.getAllFromCollection()//TODO call getAllWithContentID(identifier)
    // activitiesDB.getAllWithContentID(encodeURIComponent(request.params.id))
      .then((activities) => {

        //limit the resuls
        const start = request.params.start;
        const limit = request.params.limit;
        let activitiesLimited = activities.slice(start, start + limit);
        insertAuthorData(activities);

        //add random activities - for demonstration purpose only ; TODO remove addRandomActivities
        if (start < 200) {
          let randomActivities = getRandomActivities(activities, limit - activitiesLimited.length);
          activitiesLimited = activitiesLimited.concat(randomActivities);
        }

        let jsonReply = JSON.stringify(activitiesLimited);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });

      //TODO get activities for a deck (activities of all its decks and slides)
  },

  //Get All Activities from database for the id in the request
  getActivities: function(request, reply) {
    //Clean collection and insert mockup activities - only if request.params.id === 0
    initMockupData(request.params.id)
      .then(() => activitiesDB.getAllFromCollection()//TODO call getAllWithContentID(identifier)
      // .then(() => activitiesDB.getAllWithContentID(encodeURIComponent(request.params.id))
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      })).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });

      //TODO get activities for a deck (activities of all its decks and slides)
  },

  //Get All Activities from database for subscriptions in the request
  getActivitiesSubscribed: function(request, reply) {
    const subscriptions = request.params.subscriptions.split('/');
    let userIdArray = [];
    let slideIdArray = [];
    let deckIdArray = [];
    let idArray = [];
    subscriptions.forEach((subscription) => {
      if (subscription.startsWith('u')) {
        userIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('s')) {
        slideIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('d')) {
        deckIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('i')) {
        idArray.push(subscription.substring(1));
      }
    });

    activitiesDB.getAllWithProperties(userIdArray, slideIdArray, deckIdArray, idArray)
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });
  },

  //Get All Activities from database
  getAllActivities: function(request, reply) {
    activitiesDB.getAllFromCollection()
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });
  }
};

//Delete all and insert mockup data
function initMockupData(identifier) {
  if (identifier === '000000000000000000000000') {//create collection, delete all and insert mockup data only if the user has explicitly sent 000000000000000000000000
    return activitiesDB.createCollection()
      .then(() => activitiesDB.deleteAll())
      .then(() => insertMockupData());
  }
  return new Promise((resolve) => {resolve (1);});
}

function getRandomActivities(activities, numActivities) {

  let randomActivities = [];
  for (let i=0; i<numActivities; i++) {
    const randomIndex = Math.floor(Math.random()*1000) % activities.length;
    let a = JSON.parse(JSON.stringify(activities[randomIndex]));//clone it
    a.id = randomActivities.length;
    a.content_name = a.content_name + ' (random)';
    randomActivities.push(a);
  }
  return randomActivities;
}

function insertAuthorData(activities) {
  activities.forEach((activity) => {
    co.rewriteID(activity);
    activity.author = authorsMap.get(activity.user_id);//insert author data
  });
}

//Insert mockup data to the collection
function insertMockupData() {
  let activity1 = {
    activity_type: 'add',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000004'
  };
  let ins1 = activitiesDB.insert(activity1);
  let activity2 = {
    activity_type: 'edit',
    content_id: '112233445566778899000067',
    content_kind: 'deck',
    content_name: 'RDF Data Model',
    user_id: '112233445566778899000002'
  };
  let ins2 = ins1.then(() => activitiesDB.insert(activity2));
  let activity3 = {
    activity_type: 'translate',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    translation_info: {
      content_id: '42',
      language: 'Serbian'
    }
  };
  let ins3 = ins2.then(() => activitiesDB.insert(activity3));
  let activity4 = {
    activity_type: 'translate',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001',
    translation_info: {
      content_id: '43',
      language: 'Bosnian'
    }
  };
  let ins4 = ins3.then(() => activitiesDB.insert(activity4));
  let activity5 = {
    activity_type: 'translate',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001',
    translation_info: {
      content_id: '44',
      language: 'Croatian'
    }
  };
  let ins5 = ins4.then(() => activitiesDB.insert(activity5));
  let activity6 = {
    activity_type: 'share',
    content_id: '112233445566778899000067',
    content_kind: 'deck',
    content_name: 'RDF Data Model',
    user_id: '112233445566778899000001',
    share_info: {
      postURI: 'http://facebook.com',
      platform: 'Facebook'
    }
  };
  let ins6 = ins5.then(() => activitiesDB.insert(activity6));
  let activity7 = {
    activity_type: 'comment',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000003',
    comment_info: {
      comment_id: '112233445566778899000042',
      text: 'Awesome!'
    }
  };
  let ins7 = ins6.then(() => activitiesDB.insert(activity7));
  let activity8 = {
    activity_type: 'reply',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000003',
    comment_info: {
      comment_id: '112233445566778899000043',
      text: 'Indeed'
    }
  };
  let ins8 = ins7.then(() => activitiesDB.insert(activity8));
  let activity9 = {
    activity_type: 'use',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    use_info: {
      target_id: '53',
      target_name: 'Slidewiki Introduction'
    }
  };
  let ins9 = ins8.then(() => activitiesDB.insert(activity9));
  let activity10 = {
    activity_type: 'react',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    react_type: 'like'
  };
  let ins10 = ins9.then(() => activitiesDB.insert(activity10));
  let activity11 = {
    activity_type: 'download',
    content_id: '112233445566778899000671',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001'
  };
  let ins11 = ins10.then(() => activitiesDB.insert(activity11));

  return ins11;
}

let authorsMap = new Map([
  ['112233445566778899000001', {
    id: 7,
    username: 'Dejan P.',
    avatar: '/assets/images/mock-avatars/deadpool_256.png'
  }],
  ['112233445566778899000002', {
    id: 8,
    username: 'Nikola T.',
    avatar: '/assets/images/mock-avatars/man_512.png'
  }],
  ['112233445566778899000003', {
    id: 9,
    username: 'Marko B.',
    avatar: '/assets/images/mock-avatars/batman_512.jpg'
  }],
  ['112233445566778899000004', {
    id: 10,
    username: 'Valentina J.',
    avatar: '/assets/images/mock-avatars/ninja-simple_512.png'
  }],
  ['112233445566778899000005', {
    id: 11,
    username: 'Voice in the crowd',
    avatar: '/assets/images/mock-avatars/anon_256.jpg'
  }],
  ['112233445566778899000006', {
    id: 12,
    username: 'SlideWiki FTW',
    avatar: '/assets/images/mock-avatars/spooky_256.png'
  }],
  ['112233445566778899000000', {
    id: 13,
    username: 'Dutch',
    avatar: '/assets/images/mock-avatars/dgirl.jpeg'
  }]
]);
<commit_msg>Corrected slide id in mockup data<commit_after>/*
Handles the requests by executing stuff and replying to the client. Uses promises to get stuff done.
*/

'use strict';

const boom = require('boom'), //Boom gives us some predefined http codes and proper responses
  activitiesDB = require('../database/activitiesDatabase'), //Database functions specific for activities
  co = require('../common');

module.exports = {
  //Get Activity from database or return NOT FOUND
  getActivity: function(request, reply) {
    activitiesDB.get(encodeURIComponent(request.params.id)).then((activity) => {
      if (co.isEmpty(activity))
        reply(boom.notFound());
      else {
        activity.author = authorsMap.get(activity.user_id);//insert author data
        if (activity.author === undefined) {
          activity.author = authorsMap.get('112233445566778899000000');
        }
        reply(co.rewriteID(activity));
      }
    }).catch((error) => {

      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Create Activity with new id and payload or return INTERNAL_SERVER_ERROR
  newActivity: function(request, reply) {
    activitiesDB.insert(request.payload).then((inserted) => {
      //console.log('inserted: ', inserted);
      if (co.isEmpty(inserted.ops) || co.isEmpty(inserted.ops[0]))
        throw inserted;
      else {
        inserted.ops[0].author = authorsMap.get(inserted.ops[0].user_id);//insert author data
        reply(co.rewriteID(inserted.ops[0]));
      }
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Update Activity with id id and payload or return INTERNAL_SERVER_ERROR
  updateActivity: function(request, reply) {
    activitiesDB.replace(encodeURIComponent(request.params.id), request.payload).then((replaced) => {
      //console.log('updated: ', replaced);
      if (co.isEmpty(replaced.value))
        throw replaced;
      else
        reply(replaced.value);
    }).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Delete Activity with id id
  deleteActivity: function(request, reply) {
    activitiesDB.delete(encodeURIComponent(request.payload.id)).then(() =>
      reply({'msg': 'activity is successfully deleted...'})
    ).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Delete Activities with content id id
  deleteActivities: function(request, reply) {
    activitiesDB.deleteAllWithContentID(encodeURIComponent(request.payload.content_id)).then(() =>
      reply({'msg': 'activities are successfully deleted...'})
    ).catch((error) => {
      request.log('error', error);
      reply(boom.badImplementation());
    });
  },

  //Get All Activities from database for the id in the request, limited by the number of documents
  getActivitiesLimited: function(request, reply) {
    activitiesDB.getAllFromCollection()//TODO call getAllWithContentID(identifier)
    // activitiesDB.getAllWithContentID(encodeURIComponent(request.params.id))
      .then((activities) => {

        //limit the resuls
        const start = request.params.start;
        const limit = request.params.limit;
        let activitiesLimited = activities.slice(start, start + limit);
        insertAuthorData(activities);

        //add random activities - for demonstration purpose only ; TODO remove addRandomActivities
        if (start < 200) {
          let randomActivities = getRandomActivities(activities, limit - activitiesLimited.length);
          activitiesLimited = activitiesLimited.concat(randomActivities);
        }

        let jsonReply = JSON.stringify(activitiesLimited);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });

      //TODO get activities for a deck (activities of all its decks and slides)
  },

  //Get All Activities from database for the id in the request
  getActivities: function(request, reply) {
    //Clean collection and insert mockup activities - only if request.params.id === 0
    initMockupData(request.params.id)
      .then(() => activitiesDB.getAllFromCollection()//TODO call getAllWithContentID(identifier)
      // .then(() => activitiesDB.getAllWithContentID(encodeURIComponent(request.params.id))
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      })).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });

      //TODO get activities for a deck (activities of all its decks and slides)
  },

  //Get All Activities from database for subscriptions in the request
  getActivitiesSubscribed: function(request, reply) {
    const subscriptions = request.params.subscriptions.split('/');
    let userIdArray = [];
    let slideIdArray = [];
    let deckIdArray = [];
    let idArray = [];
    subscriptions.forEach((subscription) => {
      if (subscription.startsWith('u')) {
        userIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('s')) {
        slideIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('d')) {
        deckIdArray.push(subscription.substring(1));
      } else if (subscription.startsWith('i')) {
        idArray.push(subscription.substring(1));
      }
    });

    activitiesDB.getAllWithProperties(userIdArray, slideIdArray, deckIdArray, idArray)
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });
  },

  //Get All Activities from database
  getAllActivities: function(request, reply) {
    activitiesDB.getAllFromCollection()
      .then((activities) => {
        insertAuthorData(activities);

        let jsonReply = JSON.stringify(activities);
        reply(jsonReply);

      }).catch((error) => {
        request.log('error', error);
        reply(boom.badImplementation());
      });
  }
};

//Delete all and insert mockup data
function initMockupData(identifier) {
  if (identifier === '000000000000000000000000') {//create collection, delete all and insert mockup data only if the user has explicitly sent 000000000000000000000000
    return activitiesDB.createCollection()
      .then(() => activitiesDB.deleteAll())
      .then(() => insertMockupData());
  }
  return new Promise((resolve) => {resolve (1);});
}

function getRandomActivities(activities, numActivities) {

  let randomActivities = [];
  for (let i=0; i<numActivities; i++) {
    const randomIndex = Math.floor(Math.random()*1000) % activities.length;
    let a = JSON.parse(JSON.stringify(activities[randomIndex]));//clone it
    a.id = randomActivities.length;
    a.content_name = a.content_name + ' (random)';
    randomActivities.push(a);
  }
  return randomActivities;
}

function insertAuthorData(activities) {
  activities.forEach((activity) => {
    co.rewriteID(activity);
    activity.author = authorsMap.get(activity.user_id);//insert author data
  });
}

//Insert mockup data to the collection
function insertMockupData() {
  let activity1 = {
    activity_type: 'add',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000004'
  };
  let ins1 = activitiesDB.insert(activity1);
  let activity2 = {
    activity_type: 'edit',
    content_id: '112233445566778899000067',
    content_kind: 'deck',
    content_name: 'RDF Data Model',
    user_id: '112233445566778899000002'
  };
  let ins2 = ins1.then(() => activitiesDB.insert(activity2));
  let activity3 = {
    activity_type: 'translate',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    translation_info: {
      content_id: '42',
      language: 'Serbian'
    }
  };
  let ins3 = ins2.then(() => activitiesDB.insert(activity3));
  let activity4 = {
    activity_type: 'translate',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001',
    translation_info: {
      content_id: '43',
      language: 'Bosnian'
    }
  };
  let ins4 = ins3.then(() => activitiesDB.insert(activity4));
  let activity5 = {
    activity_type: 'translate',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001',
    translation_info: {
      content_id: '44',
      language: 'Croatian'
    }
  };
  let ins5 = ins4.then(() => activitiesDB.insert(activity5));
  let activity6 = {
    activity_type: 'share',
    content_id: '112233445566778899000067',
    content_kind: 'deck',
    content_name: 'RDF Data Model',
    user_id: '112233445566778899000001',
    share_info: {
      postURI: 'http://facebook.com',
      platform: 'Facebook'
    }
  };
  let ins6 = ins5.then(() => activitiesDB.insert(activity6));
  let activity7 = {
    activity_type: 'comment',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000003',
    comment_info: {
      comment_id: '112233445566778899000042',
      text: 'Awesome!'
    }
  };
  let ins7 = ins6.then(() => activitiesDB.insert(activity7));
  let activity8 = {
    activity_type: 'reply',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000003',
    comment_info: {
      comment_id: '112233445566778899000043',
      text: 'Indeed'
    }
  };
  let ins8 = ins7.then(() => activitiesDB.insert(activity8));
  let activity9 = {
    activity_type: 'use',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    use_info: {
      target_id: '53',
      target_name: 'Slidewiki Introduction'
    }
  };
  let ins9 = ins8.then(() => activitiesDB.insert(activity9));
  let activity10 = {
    activity_type: 'react',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000002',
    react_type: 'like'
  };
  let ins10 = ins9.then(() => activitiesDB.insert(activity10));
  let activity11 = {
    activity_type: 'download',
    content_id: '575060ae4bc68d1000ea952b',
    content_kind: 'slide',
    content_name: 'Introduction',
    user_id: '112233445566778899000001'
  };
  let ins11 = ins10.then(() => activitiesDB.insert(activity11));

  return ins11;
}

let authorsMap = new Map([
  ['112233445566778899000001', {
    id: 7,
    username: 'Dejan P.',
    avatar: '/assets/images/mock-avatars/deadpool_256.png'
  }],
  ['112233445566778899000002', {
    id: 8,
    username: 'Nikola T.',
    avatar: '/assets/images/mock-avatars/man_512.png'
  }],
  ['112233445566778899000003', {
    id: 9,
    username: 'Marko B.',
    avatar: '/assets/images/mock-avatars/batman_512.jpg'
  }],
  ['112233445566778899000004', {
    id: 10,
    username: 'Valentina J.',
    avatar: '/assets/images/mock-avatars/ninja-simple_512.png'
  }],
  ['112233445566778899000005', {
    id: 11,
    username: 'Voice in the crowd',
    avatar: '/assets/images/mock-avatars/anon_256.jpg'
  }],
  ['112233445566778899000006', {
    id: 12,
    username: 'SlideWiki FTW',
    avatar: '/assets/images/mock-avatars/spooky_256.png'
  }],
  ['112233445566778899000000', {
    id: 13,
    username: 'Dutch',
    avatar: '/assets/images/mock-avatars/dgirl.jpeg'
  }]
]);
<|endoftext|>


<commit_before>/**
  Analytics for TVOS app.  Ultimately this should mirror the Player's analytics
  plugin, but for MVP, we'll hand-roll something simple, with a lot of
  hard-coded parameters.
**/
function TVOSAnalytics() {
  var serverURL = "jwpltx.com",
    apiVersion = "v1",
    bucketName = "tvos";

  function _hashParam(s) {
    s = decodeURIComponent(s);
    var h = 0;

    for (var i = 0; i < s.length; i++) {
      var c = s.charCodeAt(i);
      h = ((h << 5) - h) + c;
      h &= h;
    }

    return `h=${h}`;
  }

  function _sendEvent(parameters) {
    var trackingArgs = [];

    for (var key in parameters) {
      var value = encodeURIComponent(parameters[key]);
      trackingArgs.push(`${key}=${value}`);
    }

    var trackingArgsStr = trackingArgs.join("&");
    var hash = _hashParam(trackingArgsStr);

    var trackerURL = `//${serverURL}/${apiVersion}/${bucketName}/ping.gif?${hash}&${trackingArgsStr}`;

    return trackerURL;

  }

}
<commit_msg>Import tracking constants from player analytics<commit_after>/**
  Analytics for TVOS app.  Ultimately this should mirror the Player's analytics
  plugin, but for MVP, we'll hand-roll something simple, with a lot of
  hard-coded parameters.
**/
function TVOSAnalytics() {
  var serverURL = "jwpltx.com",
    apiVersion = "v1",
    bucketName = "tvos";

    /** @const */ var PARAM_CHECKSUM = 'h';

    //sent with all events
    /** @const */ var PARAM_TRACKER_VERSION = 'tv';
    /** @const */ var PARAM_NONCE   = 'n';
    /** @const */ var PARAM_ANALYTICS_TOKEN = 'aid';
    /** @const */ var PARAM_EVENT_TYPE      = 'e';
    /** @const */ var PARAM_IFRAME          = 'i';
    /** @const */ var PARAM_IFRAME_DEPTH    = 'ifd';
    /** @const */ var PARAM_PLAYER_VERSION  = 'pv';
    /** @const */ var PARAM_PAGE_URL        = 'pu';
    /** @const */ var PARAM_PAGE_TITLE      = 'pt';
    /** @const */ var PARAM_SDK_PLATFORM    = 'sdk';

    // Tracking Events
    /** @const */ var EVENT_VIDEO_EMBED  = 'e';
    /** @const */ var EVENT_VIDEO_PLAY   = 's';
    /** @const */ var EVENT_TIME_WATCHED = 't';

    //mobile SDK specific
    /** @const */ var PARAM_MOBILE_SDK_VERSION  = 'sv';
    /** @const */ var PARAM_MOBILE_APP_BUNDLEID = 'bi';
    /** @const */ var PARAM_MOBILE_APP_NAME     = 'an';
    /** @const */ var PARAM_MOBILE_DEVICE_ID    = 'did';
    /** @const */ var PARAM_PLAYER_DEVICE_MODEL = 'dm';

    // Tracking Parameter Keys
    /** @const */ var PARAM_EDITION         = 'ed';
    /** @const */ var PARAM_AUTOSTART       = 'd';
    /** @const */ var PARAM_PLAYER_HOSTING  = 'ph';
    /** @const */ var PARAM_MEDIA_URL       = 'mu';
    /** @const */ var PARAM_TITLE           = 't';
    /** @const */ var PARAM_TIME_INTERVAL   = 'ti';
    /** @const */ var PARAM_TIME_WATCHED    = 'pw';
    /** @const */ var PARAM_PLAYER_SIZE     = 'ps';
    /** @const */ var PARAM_VIDEO_SIZE      = 'vs';
    /** @const */ var PARAM_PLAYER_WIDTH    = 'wd';
    /** @const */ var PARAM_PLAYER_HEIGHT   = 'pl';
    /** @const */ var PARAM_VIDEO_LENGTH    = 'l';
    /** @const */ var PARAM_QUANTILES       = 'q';
    /** @const */ var PARAM_RENDERING_MODE  = 'm';
    /** @const */ var PARAM_MEDIA_ID        = 'id';
    /** @const */ var PARAM_FLASH_VERSION   = 'fv';
    /** @const */ var PARAM_AD_BLOCK        = 'eb';
    /** @const */ var PARAM_SETUP_TIME      = 'st';
    /** @const */ var PARAM_FIRST_FRAME     = 'ff';
    /** @const */ var PARAM_PROVIDER        = 'pp';
    /** @const */ var EMBED_ID              = 'emi';
    /** @const */ var ITEM_ID               = 'pli';
    /** @const */ var PARAM_VISUAL_PLAYLIST = 'vp';
    /** @const */ var PARAM_POSTER_IMAGE    = 'po';
    /** @const */ var PARAM_SHARING         = 's';
    /** @const */ var PARAM_RELATED         = 'r';
    /** @const */ var PARAM_SKIN_NAME       = 'sn';
    /** @const */ var PARAM_CASTING_BLOCK   = 'cb';
    /** @const */ var PARAM_GA_BLOCK        = 'ga';
    /** @const */ var PARAM_PLAY_REASON     = 'pr';
    /** @const */ var PARAM_DASHBOARD_CONFIG_KEY  = 'pid';
    /** @const */ var PARAM_DISPLAY_DESCRIPTION   = 'dd';
    /** @const */ var PARAM_CHROMELESS_PLAYER     = 'cp';
    /** @const */ var PARAM_ADVERTISING_BLOCK     = 'ab';

   function _hashParam(s) {
    s = decodeURIComponent(s);
    var h = 0;

    for (var i = 0; i < s.length; i++) {
      var c = s.charCodeAt(i);
      h = ((h << 5) - h) + c;
      h &= h;
    }

    return `h=${h}`;
  }

  function _sendEvent(parameters) {
    var trackingArgs = [];

    for (var key in parameters) {
      var value = encodeURIComponent(parameters[key]);
      trackingArgs.push(`${key}=${value}`);
    }

    var trackingArgsStr = trackingArgs.join("&");
    var hash = _hashParam(trackingArgsStr);

    var trackerURL = `//${serverURL}/${apiVersion}/${bucketName}/ping.gif?${hash}&${trackingArgsStr}`;

    return trackerURL;

  }

}
<|endoftext|>


<commit_before><commit_msg>Change logic to use 'smart' as the default 'gravity'<commit_after><|endoftext|>