<commit_before>'use strict';
!function(window, document, undefined) {
  // shorter function
  var _getMsg = chrome.i18n.getMessage;
  var _storage = chrome.storage.sync;

  // global variables
  var OPTIONS;

  // elements
  var OPTIONS_BOX = id$('opt-box');
  var OPTIONS_BUTTON = id$('opt-button').tag$('button');

  // set HTML title
  document.title = _getMsg('options') + ' - ' + document.title;

  // reset the container position if the height of window is too short
  resetContainer();
  window.on('resize', resetContainer);

  getOptionsAndGenTable();

  // confirm button
  OPTIONS_BUTTON[0]
    .addText(_getMsg('confirm'))
    .on('click', saveOptions);

  // reset button
  OPTIONS_BUTTON[1]
    .addText(_getMsg('default'))
    .on('click', resetOptions);

  // donation
  id$('donate-here').on('click', function() {
    id$('donate-img').tag$('input')[2].click();
  });

  function checkOptions(storage_obj) {
    var new_options = {};

    OPTIONS.ascEach(function(option) {
      var option_name = option.name;
      if (storage_obj[option_name] === undefined) {
        storage_obj[option_name] = new_options[option_name] = option.defaultValue;

        // to remove unnecessary permissions
        setPermission(option.permissions, option_name, new_options[option_name]);
      }
    });

    if (!new_options.isEmpty()) {
      _storage.set(new_options);
    }
  }

  function genInputSelectBox(option_field, option_choices, selected_value) {
    var input_select_box = option_field.new$('div').addClass('input-select-box');

    var option_input = input_select_box.new$('input').attr({
      'type': 'text',
      'value': selected_value
    });
    var option_select = input_select_box.new$('select');

    option_choices.ascEach(function(choice) {
      if (choice !== '') {
        option_select.new$('option').prop({
          selected: choice === selected_value,
          innerText: choice
        });
      }
    });

    option_select.on('change', function() {
      option_input.value = option_select.value;
      option_input.focus();
    });

    return option_input;
  }

  function genMsgBoxWhenConfirm(msg_text) {
    var opt_msg_box = id$('opt-msg-box').empty();
    var msg_box = new$('span')
      .addText(msg_text)
      .appendTo(opt_msg_box);

    setTimeout(function() {
      opacityAnim(msg_box, -1);
    }, 3000);
  }

  function genOptionsTable() {
    _storage.get(null, function(storage_obj) {
      checkOptions(storage_obj);

      OPTIONS.ascEach(function(option) {
        var option_name = option.name;
        var option_choices = option.choices;

        var option_value = storage_obj[option_name];

        var option_box = OPTIONS_BOX.new$('div');

        var option_desc = option_box.new$('div').addClass('opt-desc');
        var option_field = option_box.new$('div').addClass('opt-input');
        var option_input;

        option_desc.innerHTML = _getMsg('opt_' + option_name);

        switch (option.type || typeof option_choices[0]) {
          case 'boolean':
            option_input = genSelectBox(option_field, option_choices, option_value);
            break;
          case 'input-select':
            option_input = genInputSelectBox(option_field, option_choices, option_value);
            break;
          case 'number':
            option_input = option_field.new$('input').prop({
              type: 'number',
              min: option_choices[0],
              max: option_choices[1],
              value: option_value
            });
            break;
          case 'string':
            option_input = option_field.new$('select');
            option_choices.ascEach(function(choice, choice_num) {
              if (choice !== '') {
                option_input.new$('option').prop({
                  value: choice_num,
                  selected: choice_num === option_value,
                  innerText: choice
                });
              }
            });
        }

        option_input.id = option_name;
      });
    });
  }

  function genSelectBox(option_field, option_choices, selected_value) {
    var selectbox_item_active = 'selectbox-item-active';
    var width_of_button = 100 / option_choices.length;

    var setActiveOption = function(option_button) {
      var button_index = option_button.index() - 2; // -2 to ignore the input and background element

      option_button.addClass(selectbox_item_active);
      cover_box.style.left = button_index * width_of_button + '%';

      hidden_input.value = option_choices[button_index];
    };

    //// generate element needed
    var selectbox = option_field.new$('div').addClass('selectbox');
    var hidden_input = selectbox.new$('input').attr('type', 'hidden');
    var cover_box = selectbox.new$('div')
      .addClass('selectbox-cover')
      .css('width', width_of_button + '%');
    ////

    option_choices.ascEach(function(value) {
      var button_text = typeof value !== 'boolean' ? value : _getMsg(value ? 'opt_yes' : 'opt_no');

      var option_button = selectbox.new$('div')
        .addClass('selectbox-item')
        .css('width', width_of_button + '%')
        .addText(button_text)
        .on('click', function() {
          if (!this.hvClass(selectbox_item_active)) {
            selectbox.class$(selectbox_item_active)[0].rmClass(selectbox_item_active);
            setActiveOption(this);
          }
        });

      if (value === selected_value) {
        setActiveOption(option_button);
      }
    });

    return hidden_input;
  }

  function getOptionsAndGenTable() {
    // options choices
    var boolean_choices = [true, false];
    var open_bookmark_choices = getSelectQueue('clickOption');

    // set global variable: OPTIONS
    OPTIONS = [
      {
        name: 'bookmarklet',
        choices: boolean_choices,
        defaultValue: false,
        permissions: ['http://*/', 'https://*/']
      },
      {
        name: 'defExpand',
        choices: null, // set on the next step
        defaultValue: 1
      },
      {
        name: 'hideMobile',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'setWidth',
        choices: [100, 399],
        defaultValue: 280
      },
      {
        name: 'fontSize',
        choices: [12, 30],
        defaultValue: 12
      },
      {
        name: 'fontFamily',
        choices: [
          'monospace',
          'sans-serif',
          'serif',
          'ArchivoNarrow',
          'Arial',
          'Comic Sans MS',
          'Georgia',
          'Lucida Sans Unicode',
          'Tahoma',
          'Trebuchet MS',
          'Verdana'
        ],
        defaultValue: 'sans-serif',
        type: 'input-select'
      },
      {
        name: 'searchTarget',
        choices: getSelectQueue('searchTargetOpt'),
        defaultValue: 0
      },
      {
        name: 'maxResults',
        choices: [10, 200],
        defaultValue: 50
      },
      {
        name: 'tooltip',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'warnOpenMany',
        choices: boolean_choices,
        defaultValue: true
      },
      {
        name: 'clickByLeft',
        choices: open_bookmark_choices,
        defaultValue: 0
      },
      {
        name: 'clickByLeftCtrl',
        choices: open_bookmark_choices,
        defaultValue: 4
      },
      {
        name: 'clickByLeftShift',
        choices: open_bookmark_choices,
        defaultValue: 5
      },
      {
        name: 'clickByMiddle',
        choices: open_bookmark_choices,
        defaultValue: 2
      },
      {
        name: 'opFolderBy',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'rememberPos',
        choices: boolean_choices,
        defaultValue: false
      }
    ];

    // get the root folders' title and set as the choices of 'defExpand'
    chrome.bookmarks.getChildren('0', function(tree) {
      var bookmark_titles = tree.map(function(x) {
        return x.title;
      });

      OPTIONS.ascEach(function(option) {
        if (option.name === 'defExpand') {
          // as '' will be skipped, the value will start from 1
          option.choices = [''].concat(bookmark_titles);
          return false;
        }
      });

      // as it is an async function, generate table here
      genOptionsTable();
    });
  }

  function getSelectQueue(option_name) {
    return _getMsg('opt_' + option_name).split('|');
  }

  function resetContainer() {
    var pos_val = window.innerHeight < container.offsetHeight ? 'auto' : '';

    container.css({
      bottom: pos_val,
      top: pos_val
    });
  }

  function resetOptions() {
    _storage.clear(function() {
      window.location.reload();
    });
  }

  function saveOptions() {
    var new_options = {};

    try {
      OPTIONS.ascEach(function(option, option_num) {
        var option_name = option.name;
        var option_choices = option.choices;
        var option_value = id$(option_name).value;

        switch (option.type || typeof option_choices[0]) {
          case 'boolean':
            option_value = option_value === 'true';
            setPermission(option.permissions, option_name, option_value);
            break;
          case 'input-select':
            option_value = option_value.trim();
            break;
          case 'number':
            option_value *= 1;
            if (isNaN(option_value) || option_value < option_choices[0] || option_value > option_choices[1]) {
              throw _getMsg('opt_error', option_num + 1 + '');
            }
            break;
          case 'string':
            option_value *= 1;
        }
        new_options[option_name] = option_value;
      });

      _storage.set(new_options);
      genMsgBoxWhenConfirm(_getMsg('opt_saved'));
    } catch(e) {
      genMsgBoxWhenConfirm(e);
    }
  }

  function setPermission(option_permissions, option_name, option_value) {
    if (option_permissions) {
      var tmp_obj = {
        permissions: [],
        origins: []
      };

      option_permissions.ascEach(function(permission) {
        tmp_obj[permission.hv('://') ? 'origins' : 'permissions'].push(permission);
      });

      chrome.permissions[option_value ? 'request' : 'remove'](tmp_obj, function(is_success) {
        if (!is_success) {
          id$(option_name).parentNode.class$('selectbox-item')[option_value ? 1 : 0].click();
          OPTIONS_BUTTON[0].click();
        }
      });
    }
  }
}(this, document);
<commit_msg>Fix wrong index when setting option 'defExpand' in Opera<commit_after>'use strict';
!function(window, document, undefined) {
  // shorter function
  var _getMsg = chrome.i18n.getMessage;
  var _storage = chrome.storage.sync;

  // global variables
  var OPTIONS;

  // elements
  var OPTIONS_BOX = id$('opt-box');
  var OPTIONS_BUTTON = id$('opt-button').tag$('button');

  // set HTML title
  document.title = _getMsg('options') + ' - ' + document.title;

  // reset the container position if the height of window is too short
  resetContainer();
  window.on('resize', resetContainer);

  getOptionsAndGenTable();

  // confirm button
  OPTIONS_BUTTON[0]
    .addText(_getMsg('confirm'))
    .on('click', saveOptions);

  // reset button
  OPTIONS_BUTTON[1]
    .addText(_getMsg('default'))
    .on('click', resetOptions);

  // donation
  id$('donate-here').on('click', function() {
    id$('donate-img').tag$('input')[2].click();
  });

  function checkOptions(storage_obj) {
    var new_options = {};

    OPTIONS.ascEach(function(option) {
      var option_name = option.name;
      if (storage_obj[option_name] === undefined) {
        storage_obj[option_name] = new_options[option_name] = option.defaultValue;

        // to remove unnecessary permissions
        setPermission(option.permissions, option_name, new_options[option_name]);
      }
    });

    if (!new_options.isEmpty()) {
      _storage.set(new_options);
    }
  }

  function genInputSelectBox(option_field, option_choices, selected_value) {
    var input_select_box = option_field.new$('div').addClass('input-select-box');

    var option_input = input_select_box.new$('input').attr({
      'type': 'text',
      'value': selected_value
    });
    var option_select = input_select_box.new$('select');

    option_choices.ascEach(function(choice) {
      option_select.new$('option').prop({
        selected: choice === selected_value,
        innerText: choice
      });
    });

    option_select.on('change', function() {
      option_input.value = option_select.value;
      option_input.focus();
    });

    return option_input;
  }

  function genMsgBoxWhenConfirm(msg_text) {
    var opt_msg_box = id$('opt-msg-box').empty();
    var msg_box = new$('span')
      .addText(msg_text)
      .appendTo(opt_msg_box);

    setTimeout(function() {
      opacityAnim(msg_box, -1);
    }, 3000);
  }

  function genOptionsTable() {
    _storage.get(null, function(storage_obj) {
      checkOptions(storage_obj);

      OPTIONS.ascEach(function(option) {
        var option_name = option.name;
        var option_choices = option.choices;

        var option_value = storage_obj[option_name];

        var option_box = OPTIONS_BOX.new$('div');

        var option_desc = option_box.new$('div').addClass('opt-desc');
        var option_field = option_box.new$('div').addClass('opt-input');
        var option_input;

        option_desc.innerHTML = _getMsg('opt_' + option_name);

        switch (option.type || typeof option_choices[0]) {
          case 'boolean':
            option_input = genSelectBox(option_field, option_choices, option_value);
            break;
          case 'input-select':
            option_input = genInputSelectBox(option_field, option_choices, option_value);
            break;
          case 'number':
            option_input = option_field.new$('input').prop({
              type: 'number',
              min: option_choices[0],
              max: option_choices[1],
              value: option_value
            });
            break;
          case 'string':
            option_input = option_field.new$('select');
            option_choices.ascEach(function(choice, choice_num) {
              if (choice !== undefined) {
                option_input.new$('option').prop({
                  value: choice_num,
                  selected: choice_num === option_value,
                  innerText: choice
                });
              }
            });
        }

        option_input.id = option_name;
      });
    });
  }

  function genSelectBox(option_field, option_choices, selected_value) {
    var selectbox_item_active = 'selectbox-item-active';
    var width_of_button = 100 / option_choices.length;

    var setActiveOption = function(option_button) {
      var button_index = option_button.index() - 2; // -2 to ignore the input and background element

      option_button.addClass(selectbox_item_active);
      cover_box.style.left = button_index * width_of_button + '%';

      hidden_input.value = option_choices[button_index];
    };

    //// generate element needed
    var selectbox = option_field.new$('div').addClass('selectbox');
    var hidden_input = selectbox.new$('input').attr('type', 'hidden');
    var cover_box = selectbox.new$('div')
      .addClass('selectbox-cover')
      .css('width', width_of_button + '%');
    ////

    option_choices.ascEach(function(value) {
      var button_text = typeof value !== 'boolean' ? value : _getMsg(value ? 'opt_yes' : 'opt_no');

      var option_button = selectbox.new$('div')
        .addClass('selectbox-item')
        .css('width', width_of_button + '%')
        .addText(button_text)
        .on('click', function() {
          if (!this.hvClass(selectbox_item_active)) {
            selectbox.class$(selectbox_item_active)[0].rmClass(selectbox_item_active);
            setActiveOption(this);
          }
        });

      if (value === selected_value) {
        setActiveOption(option_button);
      }
    });

    return hidden_input;
  }

  function getOptionsAndGenTable() {
    // options choices
    var boolean_choices = [true, false];
    var open_bookmark_choices = getSelectQueue('clickOption');

    // set global variable: OPTIONS
    OPTIONS = [
      {
        name: 'bookmarklet',
        choices: boolean_choices,
        defaultValue: false,
        permissions: ['http://*/', 'https://*/']
      },
      {
        name: 'defExpand',
        choices: [], // set on the next step
        defaultValue: 1,
        type: 'string'
      },
      {
        name: 'hideMobile',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'setWidth',
        choices: [100, 399],
        defaultValue: 280
      },
      {
        name: 'fontSize',
        choices: [12, 30],
        defaultValue: 12
      },
      {
        name: 'fontFamily',
        choices: [
          'monospace',
          'sans-serif',
          'serif',
          'ArchivoNarrow',
          'Arial',
          'Comic Sans MS',
          'Georgia',
          'Lucida Sans Unicode',
          'Tahoma',
          'Trebuchet MS',
          'Verdana'
        ],
        defaultValue: 'sans-serif',
        type: 'input-select'
      },
      {
        name: 'searchTarget',
        choices: getSelectQueue('searchTargetOpt'),
        defaultValue: 0
      },
      {
        name: 'maxResults',
        choices: [10, 200],
        defaultValue: 50
      },
      {
        name: 'tooltip',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'warnOpenMany',
        choices: boolean_choices,
        defaultValue: true
      },
      {
        name: 'clickByLeft',
        choices: open_bookmark_choices,
        defaultValue: 0
      },
      {
        name: 'clickByLeftCtrl',
        choices: open_bookmark_choices,
        defaultValue: 4
      },
      {
        name: 'clickByLeftShift',
        choices: open_bookmark_choices,
        defaultValue: 5
      },
      {
        name: 'clickByMiddle',
        choices: open_bookmark_choices,
        defaultValue: 2
      },
      {
        name: 'opFolderBy',
        choices: boolean_choices,
        defaultValue: false
      },
      {
        name: 'rememberPos',
        choices: boolean_choices,
        defaultValue: false
      }
    ];

    // get the root folders' title and set as the choices of 'defExpand'
    chrome.bookmarks.getChildren('0', function(rootfolders) {
      var def_expand_choices = OPTIONS.filter(function(x) { return x.name === 'defExpand'; })[0].choices;
      rootfolders.ascEach(function(this_folder) {
        def_expand_choices[this_folder.id * 1] = this_folder.title;
      });

      // as it is an async function, generate table here
      genOptionsTable();
    });
  }

  function getSelectQueue(option_name) {
    return _getMsg('opt_' + option_name).split('|');
  }

  function resetContainer() {
    var pos_val = window.innerHeight < container.offsetHeight ? 'auto' : '';

    container.css({
      bottom: pos_val,
      top: pos_val
    });
  }

  function resetOptions() {
    _storage.clear(function() {
      window.location.reload();
    });
  }

  function saveOptions() {
    var new_options = {};

    try {
      OPTIONS.ascEach(function(option, option_num) {
        var option_name = option.name;
        var option_choices = option.choices;
        var option_value = id$(option_name).value;

        switch (option.type || typeof option_choices[0]) {
          case 'boolean':
            option_value = option_value === 'true';
            setPermission(option.permissions, option_name, option_value);
            break;
          case 'input-select':
            option_value = option_value.trim();
            break;
          case 'number':
            option_value *= 1;
            if (isNaN(option_value) || option_value < option_choices[0] || option_value > option_choices[1]) {
              throw _getMsg('opt_error', option_num + 1 + '');
            }
            break;
          case 'string':
            option_value *= 1;
        }
        new_options[option_name] = option_value;
      });

      _storage.set(new_options);
      genMsgBoxWhenConfirm(_getMsg('opt_saved'));
    } catch(e) {
      genMsgBoxWhenConfirm(e);
    }
  }

  function setPermission(option_permissions, option_name, option_value) {
    if (option_permissions) {
      var tmp_obj = {
        permissions: [],
        origins: []
      };

      option_permissions.ascEach(function(permission) {
        tmp_obj[permission.hv('://') ? 'origins' : 'permissions'].push(permission);
      });

      chrome.permissions[option_value ? 'request' : 'remove'](tmp_obj, function(is_success) {
        if (!is_success) {
          id$(option_name).parentNode.class$('selectbox-item')[option_value ? 1 : 0].click();
          OPTIONS_BUTTON[0].click();
        }
      });
    }
  }
}(this, document);
<|endoftext|>


<commit_before>var Backbone = require('backbone'),
    _ = require('underscore'),
    $ = require('jquery'),
    template = require("../templates/reports.hbs"),
    resultsTemplate = require("../templates/stats-table.hbs"),
    hashtrack = require('hashtrack'),
    api = require('../api'),
    config = require('../config'),
    i18n = require('i18next-client')
;

var isFloat = function(n){
    return typeof n === "number" && parseInt(n) !== n;
};

var ReportTableView = Backbone.View.extend({
    ratingReportTypes: ['qos', 'communication'], // all other reports are 'totals' reports

    initialize: function (options) {
        this.chartEl = $(options.chartEl);
        this.report = options.report;
        this.results = null;
        this.flotOptions = {
            series: {bars: {show: true,
                            barWidth: 0.6,
                            align: "center"}},
            grid: {hoverable: true},
            yaxis: {min: 0,
                    tickDecimals: 0}};
        this.chartEl.bind("plothover", function (event, pos, item) {
            if (item) {
                var yStart = item.datapoint[1],
                    yEnd = item.datapoint[2],
                    yValue = yStart - yEnd;
                if (isFloat(yValue)) {
                    // round floats to 2 decimals
                    yValue = yValue.toFixed(2);
                }
                $("#report-tooltip").html(yValue)
                    .css({top: pos.pageY, left: pos.pageX+25})
                    .show();
            } else {
                $("#report-tooltip").hide();
            }
        });
        var self = this;
        $(window).resize(function () {
            if (this.resizeTimeout) {
                clearTimeout(this.resizeTimeout);
            }
            this.resizeTimeout = setTimeout(function () {
                self.render();
            }, 500);
        });
    },

    render: function () {
        var context = {loaded: false};
        if (this.results === null) {
            this.chartEl.hide();
            this.fetchReport();
        } else {
            context.loaded = true;
            context.headers = this.results.headers;
            context.rows = this.results.rows;
            this.chartEl.show();
            this.chartEl.plot(this.results.chartData, this.results.chartOptions);
            $('

')
                .text(this.results.yAxisLabel)
                .appendTo(this.chartEl);
        }

        this.$el.html(resultsTemplate(context));
        this.$el.i18n();
    },

    fetchReport: function () {
        api.request('GET', 'api/reports/' + this.report + '/')
            .then(_.bind(this.processReport, this));
    },

    isRatingReport: function() {
        return this.ratingReportTypes.indexOf(this.report) > -1;
    },

    processReport: function (data) {
        var lang = config.get('forever.language'),
            headers = null,
            rows = _.map(data, function (row) {
                var result = [row['name_' + lang] ];
                _.each(row.totals, function (total) {
                    result.push(total.total);
                });
                if (headers === null) {
                    headers = _.map(row.totals, function (total) {
                        return total['label_' + lang];
                    });
                }
                return result;
            }),
            chartData = [],
            ticks = [],
            chartOptions = this.flotOptions,
            yAxisLabel = '';

        if (this.isRatingReport()) {
            // Rating Report
            yAxisLabel = i18n.t('Reports.Chart.AverageResponse');
            _.each(data, function (row) {
                var label = row['name_' + lang],
                    numRatings = 0,
                    sumOfRatings = 0,
                    avgRating = 0;
                _.each(row.totals, function (total) {
                    var rating = Number(total.label_en);
                    numRatings += total.total;
                    sumOfRatings += (total.total * rating);
                });
                if (numRatings !== 0) {
                    avgRating = sumOfRatings / numRatings;
                }
                chartData.push({'color': row.number,
                                'data': [[row.number, avgRating]]});
                ticks.push([row.number, label]);
            });
            // Set options specific to 'Rating' chart
            chartOptions.xaxis = {ticks: ticks};
            chartOptions.yaxis.max = 5;
        } else {
            // Totals Report
            if (this.report.indexOf('num-services') > -1) {
                yAxisLabel = i18n.t('Reports.Chart.NumberServices');
            } else {
                yAxisLabel = i18n.t('Reports.Chart.NumberResponses');
            }
            var stagger = 0,
                // the more groups there are, the thinner they are
                barWidth = 1.0 / (headers.length + 1);

            chartData = _.map(headers, function (header) {
                var values = [];
                _.each(data, function (row) {
                    var rows_with_this_header = _.filter(row.totals, function (total){
                        return total['label_' + lang] === header;
                    });
                    _.each(rows_with_this_header, function (total) {
                        // offset by 'stagger' so bar is just to right of previous bar
                        values.push([row.number + stagger, total.total]);
                        ticks.push([row.number, row['name_' + lang]]);
                    });
                });
                stagger += barWidth;
                return {'label': header, 'data': values};
            });
            chartOptions.xaxis = {ticks: ticks, color: '#f3f3f4'}; // matches background
            chartOptions.series.bars.barWidth = barWidth;
            chartOptions.grid.markings = function (axes) {
                var markings = [];
                for (var x = Math.floor(axes.xaxis.min); x < axes.xaxis.max; x += 1) {
                    // make vertical gray line between groups
                    markings.push({
                        xaxis: {from: x - barWidth, to: x - barWidth},
                        color: "#aaa"
                    });
                }
                return markings;
            };
        }

        this.results = {
            headers: headers,
            rows: rows,
            chartData: chartData,
            chartOptions: chartOptions,
            yAxisLabel: yAxisLabel
        };
        this.render();
    }
});

module.exports = Backbone.View.extend({
    events: {
        'change :input[name="stat"]': 'updateReport',
        'click .download': 'downloadReport'
    },

    initialize: function () {
        this.report = hashtrack.getVar('stat') || 'wait-times';
        this.reportOptions = [
            {value: 'wait-times', label: 'WaitTime'},
            {value: 'qos', label: 'QOS'},
            {value: 'failure', label: 'Failure'},
            {value: 'communication', label: 'Communication'},
            {value: 'num-services-by-provider-type', label: 'NumServicesByProviderType'},
            {value: 'num-services-by-service-type', label: 'NumServicesByServiceType'}
        ];
    },

    render: function () {
        var context = {
            options: _.map(this.reportOptions, function (option) {
                option.selected = option.value === this.report;
                return option;
            }, this)
        };
        this.$el.html(template(context));
        this.resultsView = new ReportTableView({
            el: '#report-table',
            chartEl: '#chart',
            report: this.report
        });
        this.resultsView.render();
    },

    updateReport: function (e) {
        if (this.resultsView) {
            this.resultsView.remove();
        }
        hashtrack.setVar('stat', e.target.value);
    },

    downloadReport: function (e) {
        e.preventDefault();
        var today = new Date(),
            filename = this.report + '-' + today.toISOString().replace(/\T.*$/, '') + '.csv';
        api.request('GET', 'api/servicetypes/' + this.report + '/?format=csv')
            .then(function (response) {
                var blob = new Blob([response], {type: 'text/csv'}),
                    blobURL, link;
                // Attempt to name the saved file
                // IE supports a native saveBlob
                // https://msdn.microsoft.com/en-us/library/windows/apps/hh441122.aspx
                if (navigator.msSaveBlob) {
                    navigator.msSaveBlob(blob, filename);
                } else {
                    // Fall back to download attribute if supported
                    link = document.createElement('a');
                    blobURL = window.URL.createObjectURL(blob);
                    if ('download' in link) {
                        // Use download attribute
                        link.style = 'display: none;';
                        link.href = blobURL;
                        link.download = filename;
                        document.body.appendChild(link);
                        link.click();
                    } else {
                        // Can't control the file name
                        window.location = blobURL;
                    }
                }
            });
    }
});
<commit_msg>Show different x-axis ticks if width < 800<commit_after>var Backbone = require('backbone'),
    _ = require('underscore'),
    $ = require('jquery'),
    template = require("../templates/reports.hbs"),
    resultsTemplate = require("../templates/stats-table.hbs"),
    hashtrack = require('hashtrack'),
    api = require('../api'),
    config = require('../config'),
    i18n = require('i18next-client')
;

var isFloat = function(n){
    return typeof n === "number" && parseInt(n) !== n;
};

var ReportTableView = Backbone.View.extend({
    ratingReportTypes: ['qos', 'communication'], // all other reports are 'totals' reports

    initialize: function (options) {
        this.chartEl = $(options.chartEl);
        this.report = options.report;
        this.results = null;
        this.flotOptions = {
            series: {bars: {show: true,
                            barWidth: 0.6,
                            align: "center"}},
            grid: {hoverable: true},
            yaxis: {min: 0,
                    tickDecimals: 0}};
        this.chartEl.bind("plothover", function (event, pos, item) {
            if (item) {
                var yStart = item.datapoint[1],
                    yEnd = item.datapoint[2],
                    yValue = yStart - yEnd;
                if (isFloat(yValue)) {
                    // round floats to 2 decimals
                    yValue = yValue.toFixed(2);
                }
                $("#report-tooltip").html(yValue)
                    .css({top: pos.pageY, left: pos.pageX+25})
                    .show();
            } else {
                $("#report-tooltip").hide();
            }
        });
        var self = this;
        $(window).resize(function () {
            if (this.resizeTimeout) {
                clearTimeout(this.resizeTimeout);
            }
            this.resizeTimeout = setTimeout(function () {
                self.render();
            }, 500);
        });
    },

    render: function () {
        var context = {loaded: false};
        if (this.results === null) {
            this.chartEl.hide();
            this.fetchReport();
        } else {
            context.loaded = true;
            context.headers = this.results.headers;
            context.rows = this.results.rows;
            this.chartEl.show();
            if ($(window).width() < 800) {
                this.results.chartOptions.xaxis.ticks = this.results.mobileTicks;
            } else {
                this.results.chartOptions.xaxis.ticks = this.results.desktopTicks;
            }
            this.chartEl.plot(this.results.chartData, this.results.chartOptions);
            $('

')
                .text(this.results.yAxisLabel)
                .appendTo(this.chartEl);
        }

        this.$el.html(resultsTemplate(context));
        this.$el.i18n();
    },

    fetchReport: function () {
        api.request('GET', 'api/reports/' + this.report + '/')
            .then(_.bind(this.processReport, this));
    },

    isRatingReport: function() {
        return this.ratingReportTypes.indexOf(this.report) > -1;
    },

    processReport: function (data) {
        var lang = config.get('forever.language'),
            headers = null,
            rows = _.map(data, function (row) {
                var result = [row.number + ': ' + row['name_' + lang]];
                _.each(row.totals, function (total) {
                    result.push(total.total);
                });
                if (headers === null) {
                    headers = _.map(row.totals, function (total) {
                        return total['label_' + lang];
                    });
                }
                return result;
            }),
            chartData = [],
            ticks = [],
            mobileTicks = [],
            chartOptions = this.flotOptions,
            yAxisLabel = '';

        if (this.isRatingReport()) {
            // Rating Report
            yAxisLabel = i18n.t('Reports.Chart.AverageResponse');
            _.each(data, function (row, i) {
                var label = row['name_' + lang],
                    numRatings = 0,
                    sumOfRatings = 0,
                    avgRating = 0;
                _.each(row.totals, function (total) {
                    var rating = Number(total.label_en);
                    numRatings += total.total;
                    sumOfRatings += (total.total * rating);
                });
                if (numRatings !== 0) {
                    avgRating = sumOfRatings / numRatings;
                }
                chartData.push({'color': i,
                                'data': [[i, avgRating]]});
                ticks.push([i, label]);
                mobileTicks.push([i, row.number]);
            });
            // Set options specific to 'Rating' chart
            chartOptions.xaxis = {ticks: ticks};
            chartOptions.yaxis.max = 5;
        } else {
            // Totals Report
            if (this.report.indexOf('num-services') > -1) {
                yAxisLabel = i18n.t('Reports.Chart.NumberServices');
            } else {
                yAxisLabel = i18n.t('Reports.Chart.NumberResponses');
            }
            var stagger = 0,
                // the more groups there are, the thinner they are
                barWidth = 1.0 / (headers.length + 1);

            chartData = _.map(headers, function (header) {
                var values = [];
                _.each(data, function (row, i) {
                    var rows_with_this_header = _.filter(row.totals, function (total){
                        return total['label_' + lang] === header;
                    });
                    _.each(rows_with_this_header, function (total, j) {
                        // offset by 'stagger' so bar is just to right of previous bar
                        values.push([i + stagger, total.total]);
                        if (j === 0) {
                            ticks.push([i, row['name_' + lang]]);
                            mobileTicks.push([i, row.number]);
                        }
                    });
                });
                stagger += barWidth;
                return {'label': header, 'data': values};
            });
            chartOptions.xaxis = {ticks: ticks, color: '#f3f3f4'}; // matches background
            chartOptions.series.bars.barWidth = barWidth;
            chartOptions.grid.markings = function (axes) {
                var markings = [];
                for (var x = Math.floor(axes.xaxis.min); x < axes.xaxis.max; x += 1) {
                    // make vertical gray line between groups
                    markings.push({
                        xaxis: {from: x - barWidth, to: x - barWidth},
                        color: "#aaa"
                    });
                }
                return markings;
            };
        }

        this.results = {
            headers: headers,
            rows: rows,
            chartData: chartData,
            chartOptions: chartOptions,
            yAxisLabel: yAxisLabel,
            mobileTicks: mobileTicks,
            desktopTicks: ticks
        };
        this.render();
    }
});

module.exports = Backbone.View.extend({
    events: {
        'change :input[name="stat"]': 'updateReport',
        'click .download': 'downloadReport'
    },

    initialize: function () {
        this.report = hashtrack.getVar('stat') || 'wait-times';
        this.reportOptions = [
            {value: 'wait-times', label: 'WaitTime'},
            {value: 'qos', label: 'QOS'},
            {value: 'failure', label: 'Failure'},
            {value: 'communication', label: 'Communication'},
            {value: 'num-services-by-provider-type', label: 'NumServicesByProviderType'},
            {value: 'num-services-by-service-type', label: 'NumServicesByServiceType'}
        ];
    },

    render: function () {
        var context = {
            options: _.map(this.reportOptions, function (option) {
                option.selected = option.value === this.report;
                return option;
            }, this)
        };
        this.$el.html(template(context));
        this.resultsView = new ReportTableView({
            el: '#report-table',
            chartEl: '#chart',
            report: this.report
        });
        this.resultsView.render();
    },

    updateReport: function (e) {
        if (this.resultsView) {
            this.resultsView.remove();
        }
        hashtrack.setVar('stat', e.target.value);
    },

    downloadReport: function (e) {
        e.preventDefault();
        var today = new Date(),
            filename = this.report + '-' + today.toISOString().replace(/\T.*$/, '') + '.csv';
        api.request('GET', 'api/servicetypes/' + this.report + '/?format=csv')
            .then(function (response) {
                var blob = new Blob([response], {type: 'text/csv'}),
                    blobURL, link;
                // Attempt to name the saved file
                // IE supports a native saveBlob
                // https://msdn.microsoft.com/en-us/library/windows/apps/hh441122.aspx
                if (navigator.msSaveBlob) {
                    navigator.msSaveBlob(blob, filename);
                } else {
                    // Fall back to download attribute if supported
                    link = document.createElement('a');
                    blobURL = window.URL.createObjectURL(blob);
                    if ('download' in link) {
                        // Use download attribute
                        link.style = 'display: none;';
                        link.href = blobURL;
                        link.download = filename;
                        document.body.appendChild(link);
                        link.click();
                    } else {
                        // Can't control the file name
                        window.location = blobURL;
                    }
                }
            });
    }
});
<|endoftext|>


<commit_before>var postcss = require('postcss'),
	grid = require('../'),
	assert = require('assert');

var settings = {
	columns: 12,
	maxWidth: 960,
	gutter: 20
};

var test = function (input, output) {
    assert.equal(postcss(grid(settings)).process(input).css, output);
};

test('.row{create-row: 1320px;}', '.row{.row{display: block; margin: 0 auto; max-width: 1320px; position: relative; width: 100%; }} .row:before,.row:after{ content: " "; display: table; } .row:after{ clear: both; }');
test('.column{create-column: 40px;}', '.column{ float: left; padding: 0 20px; position: relative; width: 100%; }');
test('.small{create-grid: 12;}', '.small_1{ width: 8.33333%; } .small_2{ width: 16.66667%; } .small_3{ width: 25%; } .small_4{ width: 33.33333%; } .small_5{ width: 41.66667%; } .small_6{ width: 50%; } .small_7{ width: 58.33333%; } .small_8{ width: 66.66667%; } .small_9{ width: 75%; } .small_10{ width: 83.33333%; } .small_11{ width: 91.66667%; } .small_12{ width: 100%; }');
test('.small-offset{create-offset: 12;}', '.small-offset_0{ margin-left: 0%; } .small-offset_1{ margin-left: 8.33333%; } .small-offset_2{ margin-left: 16.66667%; } .small-offset_3{ margin-left: 25%; } .small-offset_4{ margin-left: 33.33333%; } .small-offset_5{ margin-left: 41.66667%; } .small-offset_6{ margin-left: 50%; } .small-offset_7{ margin-left: 58.33333%; } .small-offset_8{ margin-left: 66.66667%; } .small-offset_9{ margin-left: 75%; } .small-offset_10{ margin-left: 83.33333%; } .small-offset_11{ margin-left: 91.66667%; }');
test('.small-push{create-push: 12;}', '.small-push_0{ left: 0%; right: auto; } .small-push_1{ left: 8.33333%; right: auto; } .small-push_2{ left: 16.66667%; right: auto; } .small-push_3{ left: 25%; right: auto; } .small-push_4{ left: 33.33333%; right: auto; } .small-push_5{ left: 41.66667%; right: auto; } .small-push_6{ left: 50%; right: auto; } .small-push_7{ left: 58.33333%; right: auto; } .small-push_8{ left: 66.66667%; right: auto; } .small-push_9{ left: 75%; right: auto; } .small-push_10{ left: 83.33333%; right: auto; } .small-push_11{ left: 91.66667%; right: auto; }');
test('.small-pull{create-pull: 12;}', '.small-pull_0{ left: auto; right: 0%; } .small-pull_1{ left: auto; right: 8.33333%; } .small-pull_2{ left: auto; right: 16.66667%; } .small-pull_3{ left: auto; right: 25%; } .small-pull_4{ left: auto; right: 33.33333%; } .small-pull_5{ left: auto; right: 41.66667%; } .small-pull_6{ left: auto; right: 50%; } .small-pull_7{ left: auto; right: 58.33333%; } .small-pull_8{ left: auto; right: 66.66667%; } .small-pull_9{ left: auto; right: 75%; } .small-pull_10{ left: auto; right: 83.33333%; } .small-pull_11{ left: auto; right: 91.66667%; }');<commit_msg>test fix<commit_after>var postcss = require('postcss'),
	grid = require('../'),
	assert = require('assert');

var settings = {
	columns: 12,
	maxWidth: 960,
	gutter: 20
};

var test = function (input, output) {
    assert.equal(postcss(grid(settings)).process(input).css, output);
};

test('.row{create-row: 1320px;}', '.row{display: block; margin: 0 auto; max-width: 1320px; position: relative; width: 100%; } .row:before,.row:after{ content: " "; display: table; } .row:after{ clear: both; }');
test('.column{create-column: 40px;}', '.column{ float: left; padding: 0 20px; position: relative; width: 100%; }');
test('.small{create-grid: 12;}', '.small_1{ width: 8.33333%; } .small_2{ width: 16.66667%; } .small_3{ width: 25%; } .small_4{ width: 33.33333%; } .small_5{ width: 41.66667%; } .small_6{ width: 50%; } .small_7{ width: 58.33333%; } .small_8{ width: 66.66667%; } .small_9{ width: 75%; } .small_10{ width: 83.33333%; } .small_11{ width: 91.66667%; } .small_12{ width: 100%; }');
test('.small-offset{create-offset: 12;}', '.small-offset_0{ margin-left: 0%; } .small-offset_1{ margin-left: 8.33333%; } .small-offset_2{ margin-left: 16.66667%; } .small-offset_3{ margin-left: 25%; } .small-offset_4{ margin-left: 33.33333%; } .small-offset_5{ margin-left: 41.66667%; } .small-offset_6{ margin-left: 50%; } .small-offset_7{ margin-left: 58.33333%; } .small-offset_8{ margin-left: 66.66667%; } .small-offset_9{ margin-left: 75%; } .small-offset_10{ margin-left: 83.33333%; } .small-offset_11{ margin-left: 91.66667%; }');
test('.small-push{create-push: 12;}', '.small-push_0{ left: 0%; right: auto; } .small-push_1{ left: 8.33333%; right: auto; } .small-push_2{ left: 16.66667%; right: auto; } .small-push_3{ left: 25%; right: auto; } .small-push_4{ left: 33.33333%; right: auto; } .small-push_5{ left: 41.66667%; right: auto; } .small-push_6{ left: 50%; right: auto; } .small-push_7{ left: 58.33333%; right: auto; } .small-push_8{ left: 66.66667%; right: auto; } .small-push_9{ left: 75%; right: auto; } .small-push_10{ left: 83.33333%; right: auto; } .small-push_11{ left: 91.66667%; right: auto; }');
test('.small-pull{create-pull: 12;}', '.small-pull_0{ left: auto; right: 0%; } .small-pull_1{ left: auto; right: 8.33333%; } .small-pull_2{ left: auto; right: 16.66667%; } .small-pull_3{ left: auto; right: 25%; } .small-pull_4{ left: auto; right: 33.33333%; } .small-pull_5{ left: auto; right: 41.66667%; } .small-pull_6{ left: auto; right: 50%; } .small-pull_7{ left: auto; right: 58.33333%; } .small-pull_8{ left: auto; right: 66.66667%; } .small-pull_9{ left: auto; right: 75%; } .small-pull_10{ left: auto; right: 83.33333%; } .small-pull_11{ left: auto; right: 91.66667%; }');<|endoftext|>


<commit_before>'use strict'

const Fs = require('fs')
const Path = require('path')
const TemplatePath = Path.join(__dirname, './error.html')

exports.register = (server, options, next) => {

    // default option values
    const defaults = {
        showErrors: false
    }

    const config = Object.assign(defaults, options)

    // read and keep the default error template
    const errorTemplate = Fs.readFileSync(TemplatePath, 'utf8')

    // extend the request lifecycle at `onPreResponse`
    // to change the default error handling behavior (if enabled)
    server.ext('onPreResponse', (request, reply) => {

        if (!config.showErrors) {
            return reply.continue()
        }

        // response shortcut
        const response = request.response

        // only show `bad implementation` developer errors (status code 500)
        if (response.isDeveloperError) {
            const accept = request.raw.req.headers.accept
            const statusCode = response.output.payload.statusCode

            const errorResponse = {
                title: response.output.payload.error,
                statusCode: statusCode,
                message: response.message,
                method: request.raw.req.method,
                url: request.url.path,
                payload: request.raw.req.method !== 'GET' ? request.payload : '',
                stacktrace: response.stack
            }

            // take priority: check header if there's a JSON REST request
            if (accept && accept.match(/json/)) {
                return reply(errorResponse).code(statusCode)
            }

            // did the user explicitly specify an error template
            if (options.template) {
                return reply.view(options.template, errorResponse).code(statusCode)
            }

            // prepare the error template and replace `%placeholder%` with error specific details
            const output = errorTemplate.replace(/%(\w+)%/g, (full, token) => {
                return errorResponse[ token ] || ''
            })

            return reply(output).code(statusCode)
        }

        // go ahead with the response, no developer error detected
        return reply.continue()
    })

    // server.log('info', 'Plugin registered: show error stacktrace')

    next()
}

exports.register.attributes = {
    pkg: require('../package.json')
}
<commit_msg>add vision dependency for custom template; remove server.log; add headers to error data passed to custom view<commit_after>'use strict'

const Fs = require('fs')
const Path = require('path')
const TemplatePath = Path.join(__dirname, './error.html')

exports.register = (server, options, next) => {

    // default option values
    const defaults = {
        showErrors: false
    }

    const config = Object.assign(defaults, options)

    // require `vision` plugin in case the user provides an error template
    if (config.template) {
        server.dependency([ 'vision' ])
    }

    // read and keep the default error template
    const errorTemplate = Fs.readFileSync(TemplatePath, 'utf8')

    // extend the request lifecycle at `onPreResponse`
    // to change the default error handling behavior (if enabled)
    server.ext('onPreResponse', (request, reply) => {

        if (!config.showErrors) {
            return reply.continue()
        }

        // response shortcut
        const response = request.response

        // only show `bad implementation` developer errors (status code 500)
        if (response.isDeveloperError) {
            const accept = request.raw.req.headers.accept
            const statusCode = response.output.payload.statusCode

            const errorResponse = {
                title: response.output.payload.error,
                statusCode: statusCode,
                message: response.message,
                method: request.raw.req.method,
                url: request.url.path,
                headers: request.raw.req.headers,
                payload: request.raw.req.method !== 'GET' ? request.payload : '',
                stacktrace: response.stack
            }

            // take priority: check header if there's a JSON REST request
            if (accept && accept.match(/json/)) {
                return reply(errorResponse).code(statusCode)
            }

            // did the user explicitly specify an error template
            if (options.template) {
                return reply.view(options.template, errorResponse).code(statusCode)
            }

            // prepare the error template and replace `%placeholder%` with error specific details
            const output = errorTemplate.replace(/%(\w+)%/g, (full, token) => {
                return errorResponse[ token ] || ''
            })

            return reply(output).code(statusCode)
        }

        // go ahead with the response, no developer error detected
        return reply.continue()
    })

    next()
}

exports.register.attributes = {
    pkg: require('../package.json')
}
<|endoftext|>


<commit_before>const root = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  properties: {
    name: { type: 'string' },
  },
  links: [
    { rel: 'functions', href: '/functions' },
    { rel: 'healthcheck', href: '/healthcheck' },
  ],
};

const functionLinks = [
  {
    rel: 'create',
    href: '/functions/{namespace}/{id}',
    method: 'POST',
  },
  {
    rel: 'update',
    href: '/functions/{namespace}/{id}',
    method: 'PUT',
  },
  {
    rel: 'delete',
    href: '/functions/{namespace}/{id}',
    method: 'DELETE',
  },
  {
    rel: 'run',
    href: '/functions/{namespace}/{id}/run',
    method: 'PUT',
    schema: {
      type: 'object',
      properties: {
        args: {
          type: 'array',
          title: 'Arguments',
        },
      },
    },
  },
];

const functionsItemLinks = [
  {
    rel: 'self',
    href: '/functions/{namespace}/{id}',
  },
  {
    rel: 'item',
    href: '/functions/{namespace}/{id}',
  },
  {
    rel: 'parent',
    href: '/functions',
  },
];

const functionsNavigation = [
  {
    rel: 'previous',
    href: '/functions?page={previousPage}&perPage={perPage}',
  },
  {
    rel: 'next',
    href: '/functions?page={nextPage}&perPage={perPage}',
  },
  {
    rel: 'page',
    href: '/functions?page={page}&perPage={perPage}',
  },
];

const functions = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  title: 'Functions',
  properties: {
    items: {
      type: 'array',
      items: {
        $ref: '/_schemas/functions/item',
      },
    },
    previousPage: {
      type: 'integer',
    },
    nextPage: {
      type: 'integer',
    },
    page: {
      type: 'integer',
    },
    perPage: {
      type: 'integer',
    },
  },
  links: functionLinks.concat(functionsNavigation),
};

const functionItem = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  title: 'Function',
  properties: {
    id: {
      type: 'string',
    },
    code: {
      type: 'string',
    },
    hash: {
      type: 'string',
    },
  },
  required: ['code'],
  links: functionsItemLinks.concat(functionLinks),
};

exports.root = root;
exports['functions/item'] = functionItem;
exports['functions/list'] = functions;
<commit_msg>Include title of fields<commit_after>const root = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  properties: {
    name: { type: 'string' },
  },
  links: [
    { rel: 'functions', href: '/functions' },
    { rel: 'healthcheck', href: '/healthcheck' },
  ],
};

const functionLinks = [
  {
    rel: 'create',
    href: '/functions/{namespace}/{id}',
    method: 'POST',
  },
  {
    rel: 'update',
    href: '/functions/{namespace}/{id}',
    method: 'PUT',
  },
  {
    rel: 'delete',
    href: '/functions/{namespace}/{id}',
    method: 'DELETE',
  },
  {
    rel: 'run',
    href: '/functions/{namespace}/{id}/run',
    method: 'PUT',
    schema: {
      type: 'object',
      properties: {
        args: {
          type: 'array',
          title: 'Arguments',
        },
      },
    },
  },
];

const functionsItemLinks = [
  {
    rel: 'self',
    href: '/functions/{namespace}/{id}',
  },
  {
    rel: 'item',
    href: '/functions/{namespace}/{id}',
  },
  {
    rel: 'parent',
    href: '/functions',
  },
];

const functionsNavigation = [
  {
    rel: 'previous',
    href: '/functions?page={previousPage}&perPage={perPage}',
  },
  {
    rel: 'next',
    href: '/functions?page={nextPage}&perPage={perPage}',
  },
  {
    rel: 'page',
    href: '/functions?page={page}&perPage={perPage}',
  },
];

const functions = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  title: 'Functions',
  properties: {
    items: {
      type: 'array',
      items: {
        $ref: '/_schemas/functions/item',
      },
    },
    previousPage: {
      type: 'integer',
    },
    nextPage: {
      type: 'integer',
    },
    page: {
      type: 'integer',
    },
    perPage: {
      type: 'integer',
    },
  },
  links: functionLinks.concat(functionsNavigation),
};

const functionItem = {
  $schema: 'http://json-schema.org/draft-04/hyper-schema#',
  type: 'object',
  title: 'Function',
  properties: {
    id: {
      type: 'string',
      title: 'ID',
    },
    code: {
      type: 'string',
      title: 'Code',
    },
    hash: {
      type: 'string',
      title: 'Hash',
    },
  },
  required: ['code'],
  links: functionsItemLinks.concat(functionLinks),
};

exports.root = root;
exports['functions/item'] = functionItem;
exports['functions/list'] = functions;
<|endoftext|>


<commit_before>angular.module("teampot").
	factory('ProjectService',function() {
		return {
			$new: function(){
				return {
					//TODO: to be implemented
					$save: function(){}
				}
			}
		};
	});<commit_msg>Project entity service<commit_after>angular.module("teampot").
	factory('ProjectService',function(GapiClient) {

		client = GapiClient.client("teampot");

		var service = {
			$new: function(entity){
				entity = entity || {}
				entity.$save = function(){
					return client.exec("project.save",entity);
				}
				return entity;
			},
			$list: function(){
				var entityList = client.exec("project.list");
				entityList.$promise.then(function(){
					for (var i=0; i<entityList.items.length; i++) {
						service.$new(entityList.items[i]);
					}
				});
				return entityList;
			}
		};

		return service;
	});<|endoftext|>


<commit_before>// lets start this shit up

var Jay = function(n)
{
	"use strict";
	Jay.commonNodes = ["69.163.40.132","jnxt.org","nxt.noip.me","23.88.59.40","162.243.122.251"];

	this.requestType;
	Jay.requestTypes = {};
	Jay.requestTypes.singleNode = 0;
	Jay.requestTypes.multiNode = 1;
	Jay.requestTypes.autoNode = 2;
	this.txType;
	this.singleNode;
	this.isTestnet = false;
	this.init = function(node)
	{
		if(typeof(node) == "string")
		{
			this.requestType = Jay.requestTypes.singleNode;
			this.singleNode = node;
		}
	}

	this.resolveNode = function(nodeName)
	{
		var name = "http://";
		name += nodeName;
		if(this.isTestnet) name += ":6876";
		else name += ":7876";
		name += "/nxt";
		return name;
	}

	Jay.types = {};
	Jay.subtypes = {};

	Jay.oneNxt = 100000000;
	Jay.types.payment = 0;
	Jay.types.messaging = 1;
	Jay.types.asset = 2;
	Jay.types.marketplace = 3;
	Jay.types.accountControl = 4;
	Jay.types.monetarySystem = 5;

	Jay.subtypes.ordinaryPayment = 0;
	Jay.subtypes.arbitraryMessage = 0;
	Jay.subtypes.aliasAssignment = 1;
	Jay.subtypes.pollCreation = 2;
	Jay.subtypes.voteCasting = 3;
	Jay.subtypes.hubAnnouncement = 4;
	Jay.subtypes.accountInfo = 5;
	Jay.subtypes.aliasSell = 6;
	Jay.subtypes.aliasBuy = 7;
	Jay.subtypes.assetIssuance = 0;
	Jay.subtypes.assetTransfer = 1;
	Jay.subtypes.askOrderPlacement = 2;
	Jay.subtypes.bidOrderPlacement = 3;
	Jay.subtypes.askOrderCancellation = 4;
	Jay.subtypes.bidOrderCancellation = 5;
	Jay.subtypes.goodsListing = 0;
	Jay.subtypes.goodsDelisting = 1;
	Jay.subtypes.priceChange = 2;
	Jay.subtypes.quantityChange = 3;
	Jay.subtypes.purchase = 4;
	Jay.subtypes.delivery = 5;
	Jay.subtypes.feedback = 6;
	Jay.subtypes.refund = 7;
	Jay.subtypes.balanceLeasing = 0;

	Jay.appendages = {};
	Jay.appendages.none = 0;
	Jay.appendages.message = 1;
	Jay.appendages.encryptedMessage = 2;
	Jay.appendages.publicKeyAnnouncement = 4;
	Jay.appendages.encryptedMessageToSelf = 8;
	Jay.appendages.phasedTransaction = 16;

	Jay.transactionVersion = 1;
	Jay.TRFVersion = 1;
	Jay.genesisRS = "NXT-MRCC-2YLS-8M54-3CMAJ";

	Jay.epoch = 1234

	this.pad = function(length, val)
	{
    	var array = [];
    	for (var i = 0; i < length; i++)
    	{
        	array[i] = val;
    	}
    	return array;
	}

	this.positiveByteArray = function(byteArray)
	{
		return converters.hexStringToByteArray(converters.byteArrayToHexString(byteArray));
	}

	this.rsToBytes = function(rs)
	{
		var rec = new NxtAddress();
		rec.set(rs);
		var recip = (new BigInteger(rec.account_id())).toByteArray().reverse();
		if(recip.length == 9) recip = recip.slice(0, 8);
		while(recip.length < 8) recip = recip.concat(this.pad(1, 0));
		return recip;
	}
	this.numberToBytes = function(num)
	{
		var bytes = (new BigInteger((num*100000000).toString())).toByteArray().reverse();
		if(bytes.length == 9) bytes = bytes.slice(0, 8);
		while(bytes.length < 8) bytes = bytes.concat(this.pad(1, 0));
		return bytes;
	}

	this.createTrfBytes = function(type, subtype, recipient, amount, fee, attachment, appendages)
	{
		var trf = [];
		trf.push(Jay.TRFVersion);
		trf.push(type);
		trf.push(subtype + Jay.transactionVersion << 4);
		trf = trf.concat(this.rsToBytes(recipient));
		trf = trf.concat(this.numberToBytes(amount));
		trf = trf.concat(this.numberToBytes(fee));
		if(appendages == undefined) trf = trf.concat([0,0,0,0]);
		else trf = trf.concat(appendages.flags);
		if(attachment != undefined) trf = trf.concat(attachment);
		if(appendages != undefined) trf = trf.concat(this.combineAppendages(appendages));
		return this.positiveByteArray(trf);
	}

	this.createTrf = function(type, subtype, recipient, amount, fee, attachment, appendages)
	{
		var trfBytes = this.createTrfBytes(type, subtype, recipient, amount, fee, attachment, appendages);
		return this.finishTrf(trfBytes);
	}

	this.bytesToBigInteger = function(bytes)
	{
		var bi = new BigInteger("0");
		for(var a=0; a<bytes.length; a++)
		{
			bi = bi.multiply(new BigInteger("256"));
			//var term = (new BigInteger(bytes[a].toString())).multiply(multiplier);
			bi = bi.add(new BigInteger(bytes[a].toString()));

		}
		return bi;
	}

	this.base62_encode = function(bytes)
	{
		var value = this.bytesToBigInteger(bytes);
	    var buf = "";
	    while ((new BigInteger("0")).compareTo(value) < 0) {
	      	var divRem = value.divideAndRemainder(new BigInteger("62"));
	      	var remainder = divRem[1].intValue();

	      	if (remainder < 10)
	     	{
	        	buf += String.fromCharCode(remainder + '0'.charCodeAt(0));
	      	}
	      	else if (remainder < 10 + 26)
	     	{
	      		buf += String.fromCharCode(remainder + 'A'.charCodeAt(0) - 10);
	      	}
	      	else
	      	{
	        	buf += String.fromCharCode(remainder + 'a'.charCodeAt(0) - 10 - 26);
	      	}

	      	value = divRem[0];
	    }
	    buf = buf.split("").reverse().join("");
	    return buf;
	  }

	this.finishTrf = function(trfBytes)
	{
		return "TX_" + this.base62_encode(trfBytes);
	}

	this.sendMoney = function(recipient, amount, appendages)
	{
		return this.createTrf(Jay.types.payment, Jay.subtypes.ordinaryPayment, recipient, amount, 1, undefined, appendages);
	}

	this.arbitraryMessage = function(recipient, message, appendages)
	{
		var appendage = this.addAppendage(undefined, Jay.appendages.message, message);
		return this.createTrf(Jay.types.messaging, Jay.subtypes.arbitraryMessage, recipient, 0, 1, undefined, appendage);
	}

	this.aliasAssignment = function(alias, data, appendages)
	{
		var attachment = [];
		attachment.push(alias.length)
		attachment = attachment.concat(converters.stringToByteArray(alias));
		attachment = attachment.concat(this.wordBytes(data.length));
		attachment = attachment.concat(converters.stringToByteArray(data));
		return this.createTrf(Jay.types.messaging, Jay.subtypes.aliasAssignment, Jay.genesisRS, 0, 1, attachment, appendages);
	}

	this.wordBytes = function(word)
	{
		return [(word%256), Math.floor(word/256)];
	}

	this.addAppendage = function(appendages, newAppendage, newAppendageData)
	{
		var flags;
		if(appendages != undefined)
		{
			flags = converters.byteArrayToSignedInt32(appendages.flags);
		}
		flags += newAppendage;

		if(newAppendage == Jay.appendages.message)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData));
			appendages.message = data;
		}
		/*else if(newAppendage == Jay.appendages.encryptedMessage)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData);
			appendages.encryptedMessage = data;
		}*/
		/*else if(newAppendage == Jay.appendages.encryptedMessageToSelf)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData);
			appendages.encryptedMessageToSelf = data;
		}*/
		if(newAppendage == Jay.appendages.publicKeyAnnouncement)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(converters.hexStringToByteArray(newAppendageData));
			appendages.publicKeyAnnouncement = data;
		}
		appendages.flags = converters.int32ToBytes(flags);
	}

	this.combineAppendages = function(appendages)
	{
		var data = [];
		if(appendages.message != undefined)
		{
			data = data.concat(appendages.message);
		}
		if(appendages.encryptedMessage != undefined)
		{
			data = data.concat(appendages.encryptedMessage)
		}
		if(appendages.encryptedMessageToSelf != undefined)
		{
			data = data.concat(appendages.encryptedMessageToSelf)
		}
		if(appendages.publicKeyAnnouncement != undefined)
		{
			data = data.concat(appendages.publicKeyAnnouncement);
		}
		return data;
	}

	this.init(n);
};

$(document).ready(function() {

	//document.write((new Jay()).sendMoney("NXT-RJU8-JSNR-H9J4-2KWKY",100));
});<commit_msg>debug message and alias<commit_after>// lets start this shit up

var Jay = function(n)
{
	"use strict";
	Jay.commonNodes = ["69.163.40.132","jnxt.org","nxt.noip.me","23.88.59.40","162.243.122.251"];

	this.requestType;
	Jay.requestTypes = {};
	Jay.requestTypes.singleNode = 0;
	Jay.requestTypes.multiNode = 1;
	Jay.requestTypes.autoNode = 2;
	this.txType;
	this.singleNode;
	this.isTestnet = false;
	this.init = function(node)
	{
		if(typeof(node) == "string")
		{
			this.requestType = Jay.requestTypes.singleNode;
			this.singleNode = node;
		}
	}

	this.resolveNode = function(nodeName)
	{
		var name = "http://";
		name += nodeName;
		if(this.isTestnet) name += ":6876";
		else name += ":7876";
		name += "/nxt";
		return name;
	}

	Jay.types = {};
	Jay.subtypes = {};

	Jay.oneNxt = 100000000;
	Jay.types.payment = 0;
	Jay.types.messaging = 1;
	Jay.types.asset = 2;
	Jay.types.marketplace = 3;
	Jay.types.accountControl = 4;
	Jay.types.monetarySystem = 5;

	Jay.subtypes.ordinaryPayment = 0;
	Jay.subtypes.arbitraryMessage = 0;
	Jay.subtypes.aliasAssignment = 1;
	Jay.subtypes.pollCreation = 2;
	Jay.subtypes.voteCasting = 3;
	Jay.subtypes.hubAnnouncement = 4;
	Jay.subtypes.accountInfo = 5;
	Jay.subtypes.aliasSell = 6;
	Jay.subtypes.aliasBuy = 7;
	Jay.subtypes.assetIssuance = 0;
	Jay.subtypes.assetTransfer = 1;
	Jay.subtypes.askOrderPlacement = 2;
	Jay.subtypes.bidOrderPlacement = 3;
	Jay.subtypes.askOrderCancellation = 4;
	Jay.subtypes.bidOrderCancellation = 5;
	Jay.subtypes.goodsListing = 0;
	Jay.subtypes.goodsDelisting = 1;
	Jay.subtypes.priceChange = 2;
	Jay.subtypes.quantityChange = 3;
	Jay.subtypes.purchase = 4;
	Jay.subtypes.delivery = 5;
	Jay.subtypes.feedback = 6;
	Jay.subtypes.refund = 7;
	Jay.subtypes.balanceLeasing = 0;

	Jay.appendages = {};
	Jay.appendages.none = 0;
	Jay.appendages.message = 1;
	Jay.appendages.encryptedMessage = 2;
	Jay.appendages.publicKeyAnnouncement = 4;
	Jay.appendages.encryptedMessageToSelf = 8;
	Jay.appendages.phasedTransaction = 16;

	Jay.transactionVersion = 1;
	Jay.TRFVersion = 1;
	Jay.genesisRS = "NXT-MRCC-2YLS-8M54-3CMAJ";

	Jay.epoch = 1234

	this.pad = function(length, val)
	{
    	var array = [];
    	for (var i = 0; i < length; i++)
    	{
        	array[i] = val;
    	}
    	return array;
	}

	this.positiveByteArray = function(byteArray)
	{
		return converters.hexStringToByteArray(converters.byteArrayToHexString(byteArray));
	}

	this.rsToBytes = function(rs)
	{
		var rec = new NxtAddress();
		rec.set(rs);
		var recip = (new BigInteger(rec.account_id())).toByteArray().reverse();
		if(recip.length == 9) recip = recip.slice(0, 8);
		while(recip.length < 8) recip = recip.concat(this.pad(1, 0));
		return recip;
	}
	this.numberToBytes = function(num)
	{
		var bytes = (new BigInteger((num*100000000).toString())).toByteArray().reverse();
		if(bytes.length == 9) bytes = bytes.slice(0, 8);
		while(bytes.length < 8) bytes = bytes.concat(this.pad(1, 0));
		return bytes;
	}

	this.createTrfBytes = function(type, subtype, recipient, amount, fee, attachment, appendages)
	{
		var trf = [];
		trf.push(Jay.TRFVersion);
		trf.push(type);
		trf.push((subtype << 4) + (Jay.transactionVersion));
		trf = trf.concat(this.rsToBytes(recipient));
		trf = trf.concat(this.numberToBytes(amount));
		trf = trf.concat(this.numberToBytes(fee));
		if(appendages == undefined) trf = trf.concat([0,0,0,0]);
		else trf = trf.concat(appendages.flags);
		if(attachment != undefined) trf = trf.concat(attachment);
		if(appendages != undefined) trf = trf.concat(this.combineAppendages(appendages));
		return this.positiveByteArray(trf);
	}

	this.createTrf = function(type, subtype, recipient, amount, fee, attachment, appendages)
	{
		var trfBytes = this.createTrfBytes(type, subtype, recipient, amount, fee, attachment, appendages);
		return this.finishTrf(trfBytes);
	}

	this.bytesToBigInteger = function(bytes)
	{
		var bi = new BigInteger("0");
		for(var a=0; a<bytes.length; a++)
		{
			bi = bi.multiply(new BigInteger("256"));
			//var term = (new BigInteger(bytes[a].toString())).multiply(multiplier);
			bi = bi.add(new BigInteger(bytes[a].toString()));

		}
		return bi;
	}

	this.base62_encode = function(bytes)
	{
		var value = this.bytesToBigInteger(bytes);
	    var buf = "";
	    while ((new BigInteger("0")).compareTo(value) < 0) {
	      	var divRem = value.divideAndRemainder(new BigInteger("62"));
	      	var remainder = divRem[1].intValue();

	      	if (remainder < 10)
	     	{
	        	buf += String.fromCharCode(remainder + '0'.charCodeAt(0));
	      	}
	      	else if (remainder < 10 + 26)
	     	{
	      		buf += String.fromCharCode(remainder + 'A'.charCodeAt(0) - 10);
	      	}
	      	else
	      	{
	        	buf += String.fromCharCode(remainder + 'a'.charCodeAt(0) - 10 - 26);
	      	}

	      	value = divRem[0];
	    }
	    buf = buf.split("").reverse().join("");
	    return buf;
	  }

	this.finishTrf = function(trfBytes)
	{
		return "TX_" + this.base62_encode(trfBytes);
	}

	this.sendMoney = function(recipient, amount, appendages)
	{
		return this.createTrf(Jay.types.payment, Jay.subtypes.ordinaryPayment, recipient, amount, 1, undefined, appendages);
	}

	this.sendMessage = function(recipient, message, appendages)
	{
		var appendage = this.addAppendage(undefined, Jay.appendages.message, message);
		return this.createTrf(Jay.types.messaging, Jay.subtypes.arbitraryMessage, recipient, 0, 1, undefined, appendage);
	}

	this.setAlias = function(alias, data, appendages)
	{
		var attachment = [];
		attachment.push(Jay.transactionVersion);
		attachment.push(alias.length)
		attachment = attachment.concat(converters.stringToByteArray(alias));
		attachment = attachment.concat(this.wordBytes(data.length));
		attachment = attachment.concat(converters.stringToByteArray(data));
		return this.createTrf(Jay.types.messaging, Jay.subtypes.aliasAssignment, Jay.genesisRS, 0, 1, attachment, appendages);
	}

	this.wordBytes = function(word)
	{
		return [(word%256), Math.floor(word/256)];
	}

	this.addAppendage = function(appendages, newAppendage, newAppendageData)
	{
		var flags;
		if(appendages != undefined)
		{
			flags = converters.byteArrayToSignedInt32(appendages.flags);
		}
		else
		{
			appendages = {};
			flags = 0;
		}

		flags += newAppendage;

		if(newAppendage == Jay.appendages.message)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData));
			appendages.message = data;
		}
		/*else if(newAppendage == Jay.appendages.encryptedMessage)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData);
			appendages.encryptedMessage = data;
		}*/
		/*else if(newAppendage == Jay.appendages.encryptedMessageToSelf)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(this.wordBytes(newAppendageData.length));
			data = data.concat(converters.stringToByteArray(newAppendageData);
			appendages.encryptedMessageToSelf = data;
		}*/
		if(newAppendage == Jay.appendages.publicKeyAnnouncement)
		{
			var data = [];
			data.push(Jay.transactionVersion);
			data = data.concat(converters.hexStringToByteArray(newAppendageData));
			appendages.publicKeyAnnouncement = data;
		}
		appendages.flags = converters.int32ToBytes(flags);
	}

	this.combineAppendages = function(appendages)
	{
		var data = [];
		if(appendages.message != undefined)
		{
			data = data.concat(appendages.message);
		}
		if(appendages.encryptedMessage != undefined)
		{
			data = data.concat(appendages.encryptedMessage)
		}
		if(appendages.encryptedMessageToSelf != undefined)
		{
			data = data.concat(appendages.encryptedMessageToSelf)
		}
		if(appendages.publicKeyAnnouncement != undefined)
		{
			data = data.concat(appendages.publicKeyAnnouncement);
		}
		return data;
	}

	this.init(n);
};

$(document).ready(function() {

document.write((new Jay()).setAlias("abc","message"));

	//document.write((new Jay()).sendMoney("NXT-RJU8-JSNR-H9J4-2KWKY",100));
});<|endoftext|>


<commit_before><commit_msg>error in JS launch_event depreciation<commit_after><|endoftext|>


<commit_before>var async = require('async');
var fs = require('fs');
var exec = require('child_process').exec;

module.exports = function (session){
    return function (track, path, callback){

        console.log('Downloading: ' + track.title + ' by ' + track.artist.name);

        var player = session.getPlayer();

        var regex = /[\:\^\`\'\"\*\\\]\[\{\}\/\s\(\)]/g;

        if(!(fs.existsSync(path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_')))){

            if(!(fs.existsSync(path + '/' + track.artist.name.replace(regex, '_')))){
                fs.mkdirSync(path + '/' + track.artist.name.replace(regex, '_'))
            }

            fs.mkdirSync(path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_'))

        }

        var destiny = path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_') + '/' + track.name.replace(regex, '_');

        if(fs.existsSync(destiny + '.mp3')){
            console.log('Already downloaded');
            return callback(null);
        }

        var ws = fs.createWriteStream(destiny + '.raw');

        player.load(track);
        player.play();

        player.pipe(ws);
        player.once('track-end', function() {
            player.stop();
            ws.end();

            async.waterfall([

                function (callback){
                    exec('sox ' + [
                        '-r', 44100,
                        '-b', 16,
                        '-L',
                        '-c', 2,
                        '-e', 'signed-integer',
                        '-t', 'raw',
                        destiny + '.raw',
                        destiny + '.wav'].join(' '), function (err){callback(err)});
                }, function (callback){
                    exec('lame ' + [
                        '--preset', 'insane',
                        '-b', 320,
                        '-h',
                        destiny + '.wav',
                        destiny + '.mp3'].join(' '), function (err){callback(err)});
                }, function (callback){
                    track.album.coverImage(function (err, buffer){
                        if(err){ return callback(null, false)}

                        fs.writeFile(destiny + '.png', buffer, function (err){
                            callback(null, true);
                        });
                    });
                }, function (cover, callback){

                    console.log(cover);

                    var cover = ['--add-image', destiny + '.png:FRONT_COVER',];

                    var args = [
                        '-t', '"'+track.title+'"',
                        '-a', '"'+track.artist.name+'"',
                        '-A', '"'+track.album.name+'"',
                        '-Y', '"'+track.album.year+'"',
                        '-Q',
                        destiny +'.mp3'
                    ]

                    if (cover){
                        args = cover.concat(args); // Adds the command to add a ilustration to the file
                    }

                    var cmd = 'eyeD3 ' + args.join(' ');

                    exec(cmd, function (err){callback(err)});

                }, function (callback){
                    var shit = [destiny + '.raw', destiny + '.wav', destiny + '.png'];
                    async.map(shit, fs.unlink, callback)
                }

            ], function (err){
                console.log('Done');
                ws.end()
                delete player, ws
                callback(err);
            });

        });

        player.on('error', function (err){
            ws.end();
            callback(err);
        });
    }
}<commit_msg>I will fix<commit_after>var async = require('async');
var fs = require('fs');
var exec = require('child_process').exec;

module.exports = function (session){
    return function (track, path, callback){

        console.log('Downloading: ' + track.title + ' by ' + track.artist.name);

        var player = session.getPlayer();

        var regex = /[\:\^\`\'\"\*\\\]\[\{\}\/\s\(\)]/g;

        if(!(fs.existsSync(path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_')))){

            if(!(fs.existsSync(path + '/' + track.artist.name.replace(regex, '_')))){
                fs.mkdirSync(path + '/' + track.artist.name.replace(regex, '_'))
            }

            fs.mkdirSync(path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_'))

        }

        var destiny = path + '/' + track.artist.name.replace(regex, '_') + '/' + track.album.name.replace(regex, '_') + '/' + track.name.replace(regex, '_');

        if(fs.existsSync(destiny + '.mp3')){
            console.log('Already downloaded');
            return callback(null);
        }

        var ws = fs.createWriteStream(destiny + '.raw');

        player.load(track);
        player.play();

        player.pipe(ws);
        player.once('track-end', function() {
            player.stop();
            ws.end();

            async.waterfall([

                function (callback){
                    console.log('Converting raw file to wav');
                    exec('sox ' + [
                        '-r', 44100,
                        '-b', 16,
                        '-L',
                        '-c', 2,
                        '-e', 'signed-integer',
                        '-t', 'raw',
                        destiny + '.raw',
                        destiny + '.wav'].join(' '), function (err){callback(err)});
                }, function (callback){
                    console.log('Converting wav file to mp3 at 320kbps');
                    exec('lame ' + [
                        '--preset', 'insane',
                        '-b', 320,
                        '-h',
                        destiny + '.wav',
                        destiny + '.mp3'].join(' '), function (err){callback(err)});
                }, function (callback){
                    track.album.coverImage(function (err, buffer){
                        if(err){
                            return callback(null, false)
                        }
                        fs.writeFile(destiny + '.png', buffer, function (err){
                            callback(null, true);
                        });
                    });
                }, function (cover, callback){

                    console.log('Adding id3 tags');

                    var coverCmd = ['--add-image', destiny + '.png:FRONT_COVER'];

                    var args = [
                        '-t', '"'+track.title+'"',
                        '-a', '"'+track.artist.name+'"',
                        '-A', '"'+track.album.name+'"',
                        '-Y', '"'+track.album.year+'"',
                        '-Q',
                        destiny +'.mp3'
                    ]

                    if (cover){
                        args = coverCmd.concat(args); // Adds the command to add a ilustration to the file
                    }

                    var cmd = 'eyeD3 ' + args.join(' ');

                    exec(cmd, function (err){callback(err)});

                }, function (callback){
                    var shit = [destiny + '.raw', destiny + '.wav', destiny + '.png'];
                    async.map(shit, fs.unlink, callback)
                }

            ], function (err){
                console.log('Done');
                ws.end()
                delete player, ws
                callback(err);
            });

        });

        player.on('error', function (err){
            ws.end();
            callback(err);
        });
    }
}<|endoftext|>


<commit_before>var figlet = require.safe('figlet'),

constructHelpMessage = function(help, modules, context, prefix) {
	for (var i = 0; i < modules.length; i++) {
		var cmdHelp = modules[i].help.call(context, prefix);
		for (var j = 0; j < cmdHelp.length; j++) {
			help += '→ ' + cmdHelp[j][0] + '\n\t' + cmdHelp[j][1] + '\n';
		}
	}
	return help;
},

checkIfModuleExists = function(modules, moduleName) {
	return modules.find(function(element, index, array) {
		return element.name === moduleName;
	});
},

shortSummary = function(prefix) {
	var help = figlet.textSync(this.packageInfo.name.toProperCase()) + '\n '
		+ this.packageInfo.version + '\n--------------------\n'
		+ this.packageInfo.homepage +  '\n\n';

	/* Deprecated */
	var context = {
		commandPrefix: prefix
	};

	help = constructHelpMessage(help, this.coreModules, context, prefix);
	return constructHelpMessage(help, this.loadedModules, context, prefix);
},

longDescription = function(moduleName, prefix) {
	var module = checkIfModuleExists(this.coreModules, moduleName);

	if (!module || module.length === 0) {
		// Check loaded modules, as commnd not in core modules
		module = checkIfModuleExists(this.loadedModules, moduleName);
	}

	if (!module || module.length === 0) {
		return 'Cannot provide help on module that was not found. Has it been disabled?';
	}

	if (module.length > 1) {
		return 'More than one module has the same name. Please fix this before continuing.';
	}

	var help = '',
		context = {
			commandPrefix: prefix
		},
		cmdHelp = module.help.call(context, prefix);

	for (var i = 0; i < cmdHelp.length; i++) {
		var text = cmdHelp[i].length === 3 ? cmdHelp[i][2] : cmdHelp[i][1];
		help += cmdHelp[i][0] + '\n--------------------\n' + text + '\n\n';
	}
	return help;
};

exports.match = function(text, commandPrefix) {
	return text === commandPrefix + this.packageInfo.name
		|| text === commandPrefix + 'help'
		|| (text.startsWith(commandPrefix + this.packageInfo.name + ' '))
		|| text.startsWith(commandPrefix + 'help ');
};

exports.run = function(api, event) {
	var commands = event.body.split(' '),
		help = null;

	if (commands.length === 1) {
		help = shortSummary.call(this, api.commandPrefix);
	}
	else {
		commands.splice(0, 1);
		help = longDescription.call(this, commands.join(' '), api.commandPrefix);
	}

	api.sendPrivateMessage(help, event.thread_id, event.sender_id);
	return false;
};

exports.help = function(commandPrefix) {
	return [[commandPrefix + 'help','this', 'prints a short summary of all available commands'], [this.commandPrefix + 'help <query>', 'prints help for a specific module']];
};
<commit_msg>Update help.js<commit_after>var figlet = require.safe('figlet'),

constructHelpMessage = function(help, modules, context, prefix) {
	for (var i = 0; i < modules.length; i++) {
		var cmdHelp = modules[i].help.call(context, prefix);
		for (var j = 0; j < cmdHelp.length; j++) {
			help += '→ ' + cmdHelp[j][0] + '\n\t' + cmdHelp[j][1] + '\n';
		}
	}
	return help;
},

checkIfModuleExists = function(modules, moduleName) {
	return modules.find(function(element, index, array) {
		return element.name === moduleName;
	});
},

shortSummary = function(prefix) {
	var help = figlet.textSync(this.packageInfo.name.toProperCase()) + '\n '
		+ this.packageInfo.version + '\n--------------------\n'
		+ this.packageInfo.homepage +  '\n\n';

	/* Deprecated */
	var context = {
		commandPrefix: prefix
	};

	help = constructHelpMessage(help, this.coreModules, context, prefix);
	return constructHelpMessage(help, this.loadedModules, context, prefix);
},

longDescription = function(moduleName, prefix) {
	var module = checkIfModuleExists(this.coreModules, moduleName);

	if (!module || module.length === 0) {
		// Check loaded modules, as commnd not in core modules
		module = checkIfModuleExists(this.loadedModules, moduleName);
	}

	if (!module || module.length === 0) {
		return 'Cannot provide help on module that was not found. Has it been disabled?';
	}

	if (module.length > 1) {
		return 'More than one module has the same name. Please fix this before continuing.';
	}

	var help = '',
		context = {
			commandPrefix: prefix
		},
		cmdHelp = module.help.call(context, prefix);

	for (var i = 0; i < cmdHelp.length; i++) {
		var text = cmdHelp[i].length === 3 ? cmdHelp[i][2] : cmdHelp[i][1];
		help += cmdHelp[i][0] + '\n--------------------\n' + text + '\n\n';
	}
	return help;
};

exports.match = function(text, commandPrefix) {
	return text === commandPrefix + this.packageInfo.name
		|| text === commandPrefix + 'help'
		|| (text.startsWith(commandPrefix + this.packageInfo.name + ' '))
		|| text.startsWith(commandPrefix + 'help ');
};

exports.run = function(api, event) {
	var commands = event.body.split(' '),
		help = null;

	if (commands.length === 1) {
		help = shortSummary.call(this, api.commandPrefix);
	}
	else {
		commands.splice(0, 1);
		help = longDescription.call(this, commands.join(' '), api.commandPrefix);
	}

	api.sendPrivateMessage(help, event.thread_id, event.sender_id);
	return false;
};

exports.help = function(commandPrefix) {
	return [[commandPrefix + 'help','displays this help', 'prints a short summary of all available commands'], [this.commandPrefix + 'help <query>', 'prints help for a specific module']];
};
<|endoftext|>