<commit_before>'use strict';

function check(){
    // Check if every button has correct solution on it.
    var win = true;
    var loop_counter = 80;
    do{
        if(document.getElementById(loop_counter).value != puzzle[loop_counter]){
            win = false;
            break;
        }
    }while(loop_counter--);

    window.alert(
      win
        ? 'Correct! You win!'
        : 'Incorrect, try again.'
    );
}

function display_number_select(id){
    // Reset button zIndex values.
    var loop_counter = 80;
    do{
        document.getElementById(loop_counter).style.zIndex = 0;
    }while(loop_counter--);

    if(selected_button === -1
      || selected_button != id){
        selected_button = id;

        // Increase zIndex of selected button.
        document.getElementById(selected_button).style.zIndex = 2;

        // Display number-select behind selected button.
        update_number_select(id);
        document.getElementById('number-select').style.display = 'block';

    }else{
        // Hide number select.
        selected_button = -1;
        document.getElementById('number-select').style.display = 'none';
    }
}

function generate_puzzle(skip){
    if(!skip
      && !window.confirm('Generate new puzzle?')){
        return;
    }

    document.getElementById('game-area').style.marginTop =
      parseInt(document.getElementById('y-margin').value)
      + 'px';
    save();

    var first = 0;
    var second = 0;
    var which = 0;

    // Base sudoku puzzle.
    puzzle = [
      8,7,6, 5,4,3, 2,1,9,
      5,4,3, 2,1,9, 8,7,6,
      2,1,9, 8,7,6, 5,4,3,

      7,6,5, 4,3,2, 1,9,8,
      4,3,2, 1,9,8, 7,6,5,
      1,9,8, 7,6,5, 4,3,2,

      6,5,4, 3,2,1, 9,8,7,
      3,2,1, 9,8,7, 6,5,4,
      9,8,7, 6,5,4, 3,2,1,
    ];

    // Switch all instances of two random numbers 100 times.
    var loop_counter = 99;
    do{
        // Pick two different numbers between 1 and 9.
        first = Math.ceil(Math.random() * 9);
        do{
            second = Math.ceil(Math.random() * 9);
       }while(first === second);

        // Iterate through all buttons and switch those two numbers.
        times = 80;
        do{
            if(puzzle[times] === first){
                puzzle[times] = second;

            }else if(puzzle[times] === second){
                puzzle[times] = first;
            }
        }while(times--);
    }while(loop_counter--);

    // Switch columns between different blocks of 3 columns 100 times.
    loop_counter = 99;
    do{
        // Pick a column number to switch.
        which = Math.floor(Math.random() * 3);

        // Pick two different blocks of 3 columns to switch the selected column number between.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value in the selected column.
        // Swap them between the two selected blocks of 3 columns.
        times = 8;
        do{
            var temp = puzzle[9 * times + 3 * first + which];
            puzzle[9 * times + 3 * first + which] = puzzle[9 * times + 3 * second + which];
            puzzle[9 * times + 3 * second + which] = temp;
        }while(times--);
    }while(loop_counter--);

    // Switch columns within a block of 3 columns 100 times.
    loop_counter = 99;
    do{
        // Pick the block of 3 columns in which to switch two columns.
        which = Math.floor(Math.random() * 3);

        // Pick two different columns to switch.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value and swap the values between the two selected columns.
        times = 8;
        do{
            var temp = puzzle[9 * times + 3 * which + first];
            puzzle[9 * times + 3 * which + first] = puzzle[9 * times + 3 * which + second];
            puzzle[9 * times + 3 * which + second] = temp;
        }while(times--);
    }while(loop_counter--);

    // Switch random rows within a block of 3 rows 100 times.
    loop_counter = 99;
    do{
        // Pick one of the 3 blocks of 3 rows.
        which = Math.floor(Math.random() * 3);

        // Pick two different rows.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value and swap the values between the two selected rows.
        times = 8;
        do{
            var temp = puzzle[which * 27 + first * 9 + times];
            puzzle[which * 27 + first * 9 + times] = puzzle[which * 27 + second * 9 + times];
            puzzle[which * 27 + second * 9 + times] = temp;
        }while(times--);
    }while(loop_counter--);

    // Reset all buttons.
    loop_counter = 80;
    do{
        var element = document.getElementById(loop_counter);
        element.disabled = false;
        element.style.background = '#333';
        element.style.color = '#aaa';
        element.value = '';
    }while(loop_counter--);

    // Add solutions to some random buttons.
    loop_counter = document.getElementById('locked').value - 1;
    do{
        first = Math.floor(Math.random() * 81);
        var first_element = document.getElementById(first);
        var element_80 = document.getElementById(80 - first);

        first_element.disabled = true;
        element_80.disabled = true;

        first_element.style.background = '#777';
        element_80.style.background = '#777';

        first_element.style.color = '#000';
        element_80.style.color = '#000';

        first_element.value = puzzle[first];
        element_80.value = puzzle[80 - first];
    }while(loop_counter--);
}

function reset(){
    if(!window.confirm('Reset settings?')){
        return;
    }

    var ids = {
      'audio-volume': 1,
      'locked': 15,
      'y-margin': 50,
    };
    for(var id in ids){
        document.getElementById(id).value = ids[id];
    }

    save();
}

// Save settings into window.localStorage if they differ from default.
function save(){
    var ids = {
      'audio-volume': 1,
      'locked': 15,
      'y-margin': 50,
    };
    for(var id in ids){
        var value = document.getElementById(id).value;
        if(value == ids[id]
          || isNaN(value)){
            window.localStorage.removeItem('Sudoku.htm-' + id);

        }else{
            window.localStorage.setItem(
              'Sudoku.htm-' + id,
              value
            );
        }
    }
}

function select_number(number){
    document.getElementById(selected_button).value = number > 0
      ? number
      : '';
    selected_button = -1;
    document.getElementById('number-select').style.display = 'none';
}

function settings_toggle(state){
    state = state == void 0
      ? document.getElementById('settings-button').value === '+'
      : state;

    if(state){
        document.getElementById('settings').style.display = 'block';
        document.getElementById('settings-button').value = '-';

    }else{
        document.getElementById('settings').style.display = 'none';
        document.getElementById('settings-button').value = '+';
    }
}

function update_number_select(id){
    // Make sure the number select box doesn't go past the left/right edges.
    var xpos = document.getElementById(id).offsetLeft - 50 - window.pageXOffset;
    if(xpos < 0){
        xpos = 0;

    }else if(xpos > window.innerWidth - 150){
        xpos = window.innerWidth - 150;
    }

    var number_select = document.getElementById('number-select');
    number_select.style.left = xpos + 'px';

    // There is no worry of the number select box going past the top/bottom edges.
    number_select.style.top  =
      (document.getElementById(id).offsetTop  - 50 - window.pageYOffset)
      + 'px';
}

var puzzle = [];
var selected_button = -1;
var times = 0;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // G: generate a new puzzle.
    if(key === 71){
        generate_puzzle(false);

    // C: check puzzle correctness.
    }else if(key === 67){
        check();

    // ESC: hide number selection, if visible.
    }else if(selected_button != -1
      && key === 27){
        display_number_select(selected_button);

    // +: show settings.
    }else if(key === 187){
        settings_toggle(true);

    // -: hide settings.
    }else if(key === 189){
        settings_toggle(false);
    }
};

window.onload = function(){
    document.getElementById('audio-volume').value =
      parseFloat(window.localStorage.getItem('Sudoku.htm-audio-volume')) || 1;
    document.getElementById('locked').value =
      parseInt(window.localStorage.getItem('Sudoku.htm-locked')) || 15;
    document.getElementById('y-margin').value =
      parseInt(window.localStorage.getItem('Sudoku.htm-y-margin')) || 50;

    // Create buttons and add to game-area.
    var loop_counter = 80;
    var output = '';

    do{
        output +=
          '<input class=buttons id='
          + loop_counter
          + ' onclick=display_number_select('
          + loop_counter
          + ') style=background:#333 type=button>';
        if(loop_counter % 9 === 0
          && loop_counter !== 0){
            output += '
';
        }
    }while(loop_counter--);
    document.getElementById('game-area').innerHTML = output;

    // Setup margins.
    loop_counter = 8;
    do{
        document.getElementById(3 + 9 * loop_counter).style.marginRight = '5px';
        document.getElementById(27 + loop_counter).style.marginBottom = '5px';
        document.getElementById(54 + loop_counter).style.marginBottom = '5px';
        document.getElementById(6 + 9 * loop_counter).style.marginRight = '5px';
    }while(loop_counter--);

    generate_puzzle(true);
};

window.onresize
  = window.onscroll = function(e){
    // Update position of number select if visible.
    if(selected_button != -1){
        update_number_select(selected_button);
    }
};
<commit_msg>added in necessary line<commit_after>'use strict';

function check(){
    // Check if every button has correct solution on it.
    var win = true;
    var loop_counter = 80;
    do{
        if(document.getElementById(loop_counter).value != puzzle[loop_counter]){
            win = false;
            break;
        }
    }while(loop_counter--);

    window.alert(
      win
        ? 'Correct! You win!'
        : 'Incorrect, try again.'
    );
}

function display_number_select(id){
    // Reset button zIndex values.
    var loop_counter = 80;
    do{
        document.getElementById(loop_counter).style.zIndex = 0;
    }while(loop_counter--);

    if(selected_button === -1
      || selected_button != id){
        selected_button = id;

        // Increase zIndex of selected button.
        document.getElementById(selected_button).style.zIndex = 2;

        // Display number-select behind selected button.
        update_number_select(id);
        document.getElementById('number-select').style.display = 'block';

    }else{
        // Hide number select.
        selected_button = -1;
        document.getElementById('number-select').style.display = 'none';
    }
}

function generate_puzzle(skip){
    if(!skip
      && !window.confirm('Generate new puzzle?')){
        return;
    }

    document.getElementById('game-area').style.marginTop =
      parseInt(document.getElementById('y-margin').value)
      + 'px';
    save();

    var first = 0;
    var second = 0;
    var which = 0;

    // Base sudoku puzzle.
    puzzle = [
      8,7,6, 5,4,3, 2,1,9,
      5,4,3, 2,1,9, 8,7,6,
      2,1,9, 8,7,6, 5,4,3,

      7,6,5, 4,3,2, 1,9,8,
      4,3,2, 1,9,8, 7,6,5,
      1,9,8, 7,6,5, 4,3,2,

      6,5,4, 3,2,1, 9,8,7,
      3,2,1, 9,8,7, 6,5,4,
      9,8,7, 6,5,4, 3,2,1,
    ];

    // Switch all instances of two random numbers 100 times.
    var loop_counter = 99;
    do{
        // Pick two different numbers between 1 and 9.
        first = Math.ceil(Math.random() * 9);
        do{
            second = Math.ceil(Math.random() * 9);
       }while(first === second);

        // Iterate through all buttons and switch those two numbers.
        times = 80;
        do{
            if(puzzle[times] === first){
                puzzle[times] = second;

            }else if(puzzle[times] === second){
                puzzle[times] = first;
            }
        }while(times--);
    }while(loop_counter--);

    // Switch columns between different blocks of 3 columns 100 times.
    loop_counter = 99;
    do{
        // Pick a column number to switch.
        which = Math.floor(Math.random() * 3);

        // Pick two different blocks of 3 columns to switch the selected column number between.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value in the selected column.
        // Swap them between the two selected blocks of 3 columns.
        times = 8;
        do{
            var temp = puzzle[9 * times + 3 * first + which];
            puzzle[9 * times + 3 * first + which] = puzzle[9 * times + 3 * second + which];
            puzzle[9 * times + 3 * second + which] = temp;
        }while(times--);
    }while(loop_counter--);

    // Switch columns within a block of 3 columns 100 times.
    loop_counter = 99;
    do{
        // Pick the block of 3 columns in which to switch two columns.
        which = Math.floor(Math.random() * 3);

        // Pick two different columns to switch.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value and swap the values between the two selected columns.
        times = 8;
        do{
            var temp = puzzle[9 * times + 3 * which + first];
            puzzle[9 * times + 3 * which + first] = puzzle[9 * times + 3 * which + second];
            puzzle[9 * times + 3 * which + second] = temp;
        }while(times--);
    }while(loop_counter--);

    // Switch random rows within a block of 3 rows 100 times.
    loop_counter = 99;
    do{
        // Pick one of the 3 blocks of 3 rows.
        which = Math.floor(Math.random() * 3);

        // Pick two different rows.
        first = Math.floor(Math.random() * 3);
        do{
            second = Math.floor(Math.random() * 3);
        }while(first === second);

        // Iterate through each value and swap the values between the two selected rows.
        times = 8;
        do{
            var temp = puzzle[which * 27 + first * 9 + times];
            puzzle[which * 27 + first * 9 + times] = puzzle[which * 27 + second * 9 + times];
            puzzle[which * 27 + second * 9 + times] = temp;
        }while(times--);
    }while(loop_counter--);

    // Reset all buttons.
    loop_counter = 80;
    do{
        var element = document.getElementById(loop_counter);
        element.disabled = false;
        element.style.background = '#333';
        element.style.color = '#aaa';
        element.value = '';
    }while(loop_counter--);

    // Add solutions to some random buttons.
    loop_counter = document.getElementById('locked').value - 1;
    do{
        first = Math.floor(Math.random() * 81);
        var first_element = document.getElementById(first);
        var element_80 = document.getElementById(80 - first);

        first_element.disabled = true;
        element_80.disabled = true;

        first_element.style.background = '#777';
        element_80.style.background = '#777';

        first_element.style.color = '#000';
        element_80.style.color = '#000';

        first_element.value = puzzle[first];
        element_80.value = puzzle[80 - first];
    }while(loop_counter--);
}

function reset(){
    if(!window.confirm('Reset settings?')){
        return;
    }

    var ids = {
      'audio-volume': 1,
      'locked': 15,
      'y-margin': 50,
    };
    for(var id in ids){
        document.getElementById(id).value = ids[id];
    }

    save();
}

// Save settings into window.localStorage if they differ from default.
function save(){
    var ids = {
      'audio-volume': 1,
      'locked': 15,
      'y-margin': 50,
    };
    for(var id in ids){
        var value = document.getElementById(id).value;
        if(value == ids[id]
          || isNaN(value)){
            document.getElementById(id).value = ids[id];
            window.localStorage.removeItem('Sudoku.htm-' + id);

        }else{
            window.localStorage.setItem(
              'Sudoku.htm-' + id,
              value
            );
        }
    }
}

function select_number(number){
    document.getElementById(selected_button).value = number > 0
      ? number
      : '';
    selected_button = -1;
    document.getElementById('number-select').style.display = 'none';
}

function settings_toggle(state){
    state = state == void 0
      ? document.getElementById('settings-button').value === '+'
      : state;

    if(state){
        document.getElementById('settings').style.display = 'block';
        document.getElementById('settings-button').value = '-';

    }else{
        document.getElementById('settings').style.display = 'none';
        document.getElementById('settings-button').value = '+';
    }
}

function update_number_select(id){
    // Make sure the number select box doesn't go past the left/right edges.
    var xpos = document.getElementById(id).offsetLeft - 50 - window.pageXOffset;
    if(xpos < 0){
        xpos = 0;

    }else if(xpos > window.innerWidth - 150){
        xpos = window.innerWidth - 150;
    }

    var number_select = document.getElementById('number-select');
    number_select.style.left = xpos + 'px';

    // There is no worry of the number select box going past the top/bottom edges.
    number_select.style.top  =
      (document.getElementById(id).offsetTop  - 50 - window.pageYOffset)
      + 'px';
}

var puzzle = [];
var selected_button = -1;
var times = 0;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // G: generate a new puzzle.
    if(key === 71){
        generate_puzzle(false);

    // C: check puzzle correctness.
    }else if(key === 67){
        check();

    // ESC: hide number selection, if visible.
    }else if(selected_button != -1
      && key === 27){
        display_number_select(selected_button);

    // +: show settings.
    }else if(key === 187){
        settings_toggle(true);

    // -: hide settings.
    }else if(key === 189){
        settings_toggle(false);
    }
};

window.onload = function(){
    document.getElementById('audio-volume').value =
      parseFloat(window.localStorage.getItem('Sudoku.htm-audio-volume')) || 1;
    document.getElementById('locked').value =
      parseInt(window.localStorage.getItem('Sudoku.htm-locked')) || 15;
    document.getElementById('y-margin').value =
      parseInt(window.localStorage.getItem('Sudoku.htm-y-margin')) || 50;

    // Create buttons and add to game-area.
    var loop_counter = 80;
    var output = '';

    do{
        output +=
          '<input class=buttons id='
          + loop_counter
          + ' onclick=display_number_select('
          + loop_counter
          + ') style=background:#333 type=button>';
        if(loop_counter % 9 === 0
          && loop_counter !== 0){
            output += '
';
        }
    }while(loop_counter--);
    document.getElementById('game-area').innerHTML = output;

    // Setup margins.
    loop_counter = 8;
    do{
        document.getElementById(3 + 9 * loop_counter).style.marginRight = '5px';
        document.getElementById(27 + loop_counter).style.marginBottom = '5px';
        document.getElementById(54 + loop_counter).style.marginBottom = '5px';
        document.getElementById(6 + 9 * loop_counter).style.marginRight = '5px';
    }while(loop_counter--);

    generate_puzzle(true);
};

window.onresize
  = window.onscroll = function(e){
    // Update position of number select if visible.
    if(selected_button != -1){
        update_number_select(selected_button);
    }
};
<|endoftext|>


<commit_before>// sensable - send measurements to http://sensable.io

var sensable    = require('sensable-reporter')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , utility     = require('./../../core/utility')
  , broker      = utility.broker
  , indicator   = require('./../device-indicator')
  , sensor      = require('./../device-sensor')
  ;

var logger = indicator.logger;

var Sensable = exports.Device = function(deviceID, deviceUID, info) {
  var self = this;

  self.whatami = info.deviceType;
  self.deviceID = deviceID.toString();
  self.deviceUID = deviceUID;
  self.name = info.device.name;
  self.getName();

  self.info = utility.clone(info);
  delete(self.info.id);
  delete(self.info.device);
  delete(self.info.deviceType);
  self.status = 'ready';
  self.elide = [ 'token' ];
  self.changed();

  broker.subscribe('readings', function(deviceID, point) { self.update(self, deviceID, point); });

  broker.subscribe('actors', function(request, taskID, actor, perform, parameter) {
    if (request === 'attention') {
      if (self.status === 'error') self.alert('please check login credentials at https://sensable.io/');
      return;
    }

    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'perform') return self.perform(self, taskID, perform, parameter);
  });

  self.normalize(self);
};
util.inherits(Sensable, indicator.Device);

Sensable.prototype.normalize = function(self) {
  var deviceID, i;

  if ((util.isArray(self.info.measurements)) && (self.info.measurements.length > 0) && (!self.measurements)) {
    self.measurements = {};
    for (i = 0; i < self.info.measurements.length; i++) self.measurements[self.info.measurements[i]] = true;
  }

  if ((util.isArray(self.info.sensors)) && (self.info.sensors.length > 0) && (!self.sensors)) {
    self.sensors = {};
    for (i = 0; i < self.info.sensors.length; i++) {
      deviceID = self.info.sensors[i].split('/')[1];
      self.sensors[deviceID] = true;
    }
  }
};

Sensable.prototype.update = function(self, deviceID, point) {
  var actor, device, entity, location, place;

  if (self.status !== 'ready') return;
  if ((!!self.sensors) && (!self.sensors[deviceID])) return;
  if ((!!self.measurements) && (!self.measurements[point.measure.name])) return;

  point.device = { deviceID: deviceID };
  actor = steward.actors.device;
  if (!!actor) {
    entity = actor.$lookup(deviceID);
    if (!!entity) device = entity.proplist();
    if (!!device) point.device.name = device.name;
    if (!!device.info) location = device.info.location;
  }

  if (!location) {
    actor = steward.actors.place;
    if (!!actor) {
      entity = actor.$lookup("1");
      if (!!entity) place = entity.proplist();
      if (!!place) location = place.info && place.info.location;
    }
  }
  if (!!location) location = [ parseFloat(location[0]), parseFloat(location[1]) ]; else location = [ 0, 0 ];
  if (self.info.private !== 'off') location = [ parseFloat(location[0].toFixed(3)), parseFloat(location[1].toFixed(3)) ];

  sensable({ sensorid    : 'device/' + deviceID + '.' + point.measure.name
           , unit        : point.measure.label
           , sensortype  : point.measure.name
           , latitude    : location[0]
           , longitude   : location[1]
           }
          ,{ accessToken : self.info.token
           , private     : self.info.private !== 'off'
           }).upload(point.value, point.timestamp, function(err) {
    if (!err) return;

    logger.error('device/' + self.deviceID, { event: 'uplaod', diagnostic: err.message });
    if (self.status === 'error') return;
    self.status = 'error';
    self.changed();
  });
};

Sensable.prototype.perform = function(self, taskID, perform, parameter) {
  var params, updateP;

  try { params = JSON.parse(parameter); } catch(ex) { params = {}; }

  if (perform !== 'set') return false;

  if (!!params.name) self.setName(params.name);

  updateP = false;
  if (!!params.token) {
    updateP = true;
    self.info.token = params.token;
  }
  if ((!!params.private) && ((params.private === 'on') || (params.private === 'off'))) {
    updateP = true;
    self.info.private = params.private;
  }
  if ((!!params.measurements) && (util.isArray(params.measurements))) {
    updateP = true;
    self.info.measurements = params.measurements;
    delete(self.measurements);
  }
  if ((!!params.sensors) && (util.isArray(params.sensors))) {
    updateP = true;
    self.info.sensors = params.sensors;
    delete(self.sensors);
  }
  if (updateP) self.setInfo();

  self.normalize(self);
  return steward.performed(taskID);
};

var validate_create = function(info) {
  var result = { invalid: [], requires: [] };

  if ((!!info.token) && (typeof info.token !== 'string')) result.invalid.push('key');

  if (!info.token) result.requires.push('token');
  else if ((typeof info.token !== 'string') || (info.token.length < 40)) result.invalid.push('token');

  if ((!!info.private) && (info.private !== 'on') && (info.private !== 'off')) result.invalid.push('private');

  if ((!!info.measurements) && (!util.isArray(info.measurements))) result.invalid.push('measurements');
  if ((!!info.sensors) && (!util.isArray(info.sensors))) result.invalid.push('sensors');

  return result;
};

var validate_perform = function(perform, parameter) {
  var params = {}
    , result = { invalid: [], requires: [] }
    ;

  if (!!parameter) try { params = JSON.parse(parameter); } catch(ex) { result.invalid.push('parameter'); }

  if (perform === 'set') {
    if (!params.token) params.token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
    return validate_create(params);
  }

  result.invalid.push('perform');
  return result;
};

exports.start = function() {
  var measureName, measurements;

  steward.actors.device.indicator.sensable = steward.actors.device.indicator.sensable ||
      { $info     : { type: '/device/indicator/sensable' } };

  measurements = {};
  for (measureName in sensor.measures) {
    if (sensor.measures.hasOwnProperty(measureName)) measurements[measureName] = sensor.measures[measureName].units;
  }

  steward.actors.device.indicator.sensable.sensor =
      { $info     : { type       : '/device/indicator/sensable/sensor'
                    , observe    : [ ]
                    , perform    : [ ]
                    , properties : { name         : true
                                   , status       : [ 'ready', 'waiting', 'error' ]
                                   , token        : true
                                   , private      : [ 'on', 'off' ]
                                   , measurements : measurements
                                   , sensors      : []
                                   }
                    }
      , $validate : { create     : validate_create
                    , perform    : validate_perform
                    }
      };
  devices.makers['/device/indicator/sensable/sensor'] = Sensable;
};
<commit_msg>inverted sense of private for sensable-reporter<commit_after>// sensable - send measurements to http://sensable.io

var sensable    = require('sensable-reporter')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , utility     = require('./../../core/utility')
  , broker      = utility.broker
  , indicator   = require('./../device-indicator')
  , sensor      = require('./../device-sensor')
  ;

var logger = indicator.logger;

var Sensable = exports.Device = function(deviceID, deviceUID, info) {
  var self = this;

  self.whatami = info.deviceType;
  self.deviceID = deviceID.toString();
  self.deviceUID = deviceUID;
  self.name = info.device.name;
  self.getName();

  self.info = utility.clone(info);
  delete(self.info.id);
  delete(self.info.device);
  delete(self.info.deviceType);
  self.status = 'ready';
  self.elide = [ 'token' ];
  self.changed();

  broker.subscribe('readings', function(deviceID, point) { self.update(self, deviceID, point); });

  broker.subscribe('actors', function(request, taskID, actor, perform, parameter) {
    if (request === 'attention') {
      if (self.status === 'error') self.alert('please check login credentials at https://sensable.io/');
      return;
    }

    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'perform') return self.perform(self, taskID, perform, parameter);
  });

  self.normalize(self);
};
util.inherits(Sensable, indicator.Device);

Sensable.prototype.normalize = function(self) {
  var deviceID, i;

  if ((util.isArray(self.info.measurements)) && (self.info.measurements.length > 0) && (!self.measurements)) {
    self.measurements = {};
    for (i = 0; i < self.info.measurements.length; i++) self.measurements[self.info.measurements[i]] = true;
  }

  if ((util.isArray(self.info.sensors)) && (self.info.sensors.length > 0) && (!self.sensors)) {
    self.sensors = {};
    for (i = 0; i < self.info.sensors.length; i++) {
      deviceID = self.info.sensors[i].split('/')[1];
      self.sensors[deviceID] = true;
    }
  }
};

Sensable.prototype.update = function(self, deviceID, point) {
  var actor, device, entity, location, place;

  if (self.status !== 'ready') return;
  if ((!!self.sensors) && (!self.sensors[deviceID])) return;
  if ((!!self.measurements) && (!self.measurements[point.measure.name])) return;

  point.device = { deviceID: deviceID };
  actor = steward.actors.device;
  if (!!actor) {
    entity = actor.$lookup(deviceID);
    if (!!entity) device = entity.proplist();
    if (!!device) point.device.name = device.name;
    if (!!device.info) location = device.info.location;
  }

  if (!location) {
    actor = steward.actors.place;
    if (!!actor) {
      entity = actor.$lookup("1");
      if (!!entity) place = entity.proplist();
      if (!!place) location = place.info && place.info.location;
    }
  }
  if (!!location) location = [ parseFloat(location[0]), parseFloat(location[1]) ]; else location = [ 0, 0 ];
  if (self.info.private === 'off') location = [ parseFloat(location[0].toFixed(3)), parseFloat(location[1].toFixed(3)) ];

  sensable({ sensorid    : 'device/' + deviceID + '.' + point.measure.name
           , unit        : point.measure.label
           , sensortype  : point.measure.name
           , latitude    : location[0]
           , longitude   : location[1]
           }
          ,{ accessToken : self.info.token
           , private     : self.info.private !== 'off'
           }).upload(point.value, point.timestamp, function(err) {
    if (!err) return;

    logger.error('device/' + self.deviceID, { event: 'uplaod', diagnostic: err.message });
    if (self.status === 'error') return;
    self.status = 'error';
    self.changed();
  });
};

Sensable.prototype.perform = function(self, taskID, perform, parameter) {
  var params, updateP;

  try { params = JSON.parse(parameter); } catch(ex) { params = {}; }

  if (perform !== 'set') return false;

  if (!!params.name) self.setName(params.name);

  updateP = false;
  if (!!params.token) {
    updateP = true;
    self.info.token = params.token;
  }
  if ((!!params.private) && ((params.private === 'on') || (params.private === 'off'))) {
    updateP = true;
    self.info.private = params.private;
  }
  if ((!!params.measurements) && (util.isArray(params.measurements))) {
    updateP = true;
    self.info.measurements = params.measurements;
    delete(self.measurements);
  }
  if ((!!params.sensors) && (util.isArray(params.sensors))) {
    updateP = true;
    self.info.sensors = params.sensors;
    delete(self.sensors);
  }
  if (updateP) self.setInfo();

  self.normalize(self);
  return steward.performed(taskID);
};

var validate_create = function(info) {
  var result = { invalid: [], requires: [] };

  if ((!!info.token) && (typeof info.token !== 'string')) result.invalid.push('key');

  if (!info.token) result.requires.push('token');
  else if ((typeof info.token !== 'string') || (info.token.length < 40)) result.invalid.push('token');

  if ((!!info.private) && (info.private !== 'on') && (info.private !== 'off')) result.invalid.push('private');

  if ((!!info.measurements) && (!util.isArray(info.measurements))) result.invalid.push('measurements');
  if ((!!info.sensors) && (!util.isArray(info.sensors))) result.invalid.push('sensors');

  return result;
};

var validate_perform = function(perform, parameter) {
  var params = {}
    , result = { invalid: [], requires: [] }
    ;

  if (!!parameter) try { params = JSON.parse(parameter); } catch(ex) { result.invalid.push('parameter'); }

  if (perform === 'set') {
    if (!params.token) params.token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
    return validate_create(params);
  }

  result.invalid.push('perform');
  return result;
};

exports.start = function() {
  var measureName, measurements;

  steward.actors.device.indicator.sensable = steward.actors.device.indicator.sensable ||
      { $info     : { type: '/device/indicator/sensable' } };

  measurements = {};
  for (measureName in sensor.measures) {
    if (sensor.measures.hasOwnProperty(measureName)) measurements[measureName] = sensor.measures[measureName].units;
  }

  steward.actors.device.indicator.sensable.sensor =
      { $info     : { type       : '/device/indicator/sensable/sensor'
                    , observe    : [ ]
                    , perform    : [ ]
                    , properties : { name         : true
                                   , status       : [ 'ready', 'waiting', 'error' ]
                                   , token        : true
                                   , private      : [ 'on', 'off' ]
                                   , measurements : measurements
                                   , sensors      : []
                                   }
                    }
      , $validate : { create     : validate_create
                    , perform    : validate_perform
                    }
      };
  devices.makers['/device/indicator/sensable/sensor'] = Sensable;
};
<|endoftext|>


<commit_before>var _ = require("lodash");
var Future = require("fibers/future");
var evalRuleInFiber = require("./evalRuleInFiber");
var selectRulesToEvalFuture = Future.wrap(require("./selectRulesToEval"));

module.exports = function(ctx, pico_id){
  ctx.emit("debug", "event recieved");

  ctx.pico = ctx.db.getPicoFuture(pico_id).wait();
  if(!ctx.pico){
    throw new Error("Invalid eci: " + ctx.event.eci);
  }

  ctx.emit("debug", "pico selected");

  var rules = selectRulesToEvalFuture(ctx).wait();
  var responses = _.map(rules, function(rule){

    ctx.emit("debug", "rule selected: " + rule.rid + " -> " + rule.name);

    ctx.rid = rule.rid;
    ctx.rule = rule;
    ctx.scope = rule.scope;
    if(_.has(ctx.rulesets, rule.rid)){
      ctx.modules_used = ctx.rulesets[rule.rid].modules_used;
    }

    return evalRuleInFiber(rule, ctx);
  });

  var res_by_type = _.groupBy(_.flattenDeep(_.values(responses)), "type");

  var r = _.mapValues(res_by_type, function(responses, key){
    if(key === "directive"){
      return _.map(responses, function(d){
        return _.omit(d, "type");
      });
    }
    return responses;
  });

  if(_.has(r, "directive")){
    r.directives = r.directive;
    delete r.directive;
  }

  return r;
};
<commit_msg>{directives: []}<commit_after>var _ = require("lodash");
var Future = require("fibers/future");
var evalRuleInFiber = require("./evalRuleInFiber");
var selectRulesToEvalFuture = Future.wrap(require("./selectRulesToEval"));

module.exports = function(ctx, pico_id){
  ctx.emit("debug", "event recieved");

  ctx.pico = ctx.db.getPicoFuture(pico_id).wait();
  if(!ctx.pico){
    throw new Error("Invalid eci: " + ctx.event.eci);
  }

  ctx.emit("debug", "pico selected");

  var rules = selectRulesToEvalFuture(ctx).wait();
  var responses = _.map(rules, function(rule){

    ctx.emit("debug", "rule selected: " + rule.rid + " -> " + rule.name);

    ctx.rid = rule.rid;
    ctx.rule = rule;
    ctx.scope = rule.scope;
    if(_.has(ctx.rulesets, rule.rid)){
      ctx.modules_used = ctx.rulesets[rule.rid].modules_used;
    }

    return evalRuleInFiber(rule, ctx);
  });

  var res_by_type = _.groupBy(_.flattenDeep(_.values(responses)), "type");

  var r = _.mapValues(res_by_type, function(responses, key){
    if(key === "directive"){
      return _.map(responses, function(d){
        return _.omit(d, "type");
      });
    }
    return responses;
  });

  if(_.has(r, "directive")){
    r.directives = r.directive;
    delete r.directive;
  }else{
    //we always want to return a directives array even if it's empty
    r.directives = [];
  }

  return r;
};
<|endoftext|>


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

RG.Object = {};

RG.Object.Defense = function() {
    this._attack = 1;
    this._defense = 1;
    this._protection = 0;
};

RG.Object.Defense.prototype.getAttack = function() {return this._attack;};
RG.Object.Defense.prototype.setAttack = function(attack) {
    this._attack = attack;
};

/* Defense related methods.*/
RG.Object.Defense.prototype.getDefense = function() { return this._defense; };
RG.Object.Defense.prototype.setDefense = function(defense) {
    this._defense = defense;
};

RG.Object.Defense.prototype.getProtection = function() {
    return this._protection;
};
RG.Object.Defense.prototype.setProtection = function(prot) {
    this._protection = prot;
};

RG.Object.Defense.prototype.copy = function(rhs) {
    this.setAttack(rhs.getAttack());
    this.setDefense(rhs.getDefense());
    this.setProtection(rhs.getProtection());
};

RG.Object.Defense.prototype.equals = function(rhs) {
    const res = this.getAttack() === rhs.getAttack() &&
        this.getDefense() === rhs.getDefense() &&
        this.getProtection() === rhs.getProtection();
    return res;
};

RG.Object.Defense.prototype.toJSON = function() {
    const json = {
        setAttack: this.getAttack(),
        setDefense: this.getDefense(),
        setProtection: this.getProtection()
    };
    return json;
};

/* Damage object used in Weapons and other damaging things. */
RG.Object.Damage = function() {
    RG.Object.Defense.call(this);
    let _damageDie = new RG.Die(1, 4, 0);
    let _range = 1;

    /* Attack methods. */
    this.setAttackRange = range => {_range = range;};
    this.getAttackRange = () => _range;

    this.rollDamage = function() {
        if (this.hasOwnProperty('getWeapon')) {
            const weapon = this.getWeapon();
            if (!RG.isNullOrUndef([weapon])) {
                return weapon.rollDamage();
            }
        }
        return _damageDie.roll();
    };

    this.getDamageDie = () => _damageDie;

    this.setDamageDie = dStr => {
        if (typeof dStr === 'string') {
            _damageDie = RG.FACT.createDie(dStr);
        }
        else if (typeof dStr === 'object') {
            _damageDie = dStr;
        }
    };

};
RG.extend2(RG.Object.Damage, RG.Object.Defense);

RG.Object.Damage.prototype.copy = function(rhs) {
    RG.Object.Defense.prototype.copy.call(this, rhs);
    this.setAttackRange(rhs.getAttackRange());
    const die = new RG.Die();
    die.copy(rhs.getDamageDie());
    this.setDamageDie(die);
};

RG.Object.Damage.prototype.equals = function(rhs) {
    var res = RG.Object.Defense.prototype.equals.call(this, rhs);
    if (res) {
        res = this.getDamageDie().equals(rhs.getDamageDie());
        res = res && this.getAttackRange() === rhs.getAttackRange();
    }
    return res;
};

RG.Object.Damage.prototype.toString = function() {
    var msg = ' A: ' + this.getAttack() + ', D: ' + this.getDefense() + ', ';
    msg += 'Dmg: ' + this.getDamageDie().toString();
    msg += ',R:' + this.getAttackRange();
    return msg;
};

RG.Object.Damage.prototype.toJSON = function() {
    var json = RG.Object.Defense.prototype.toJSON.call(this);
    json.setAttackRange = this.getAttackRange();
    json.setDamageDie = this.getDamageDie().toString();
    return json;
};

/* Typed objects should inherit from this. */
RG.Object.Typed = function(propType, type) {
    this.type = type;
    this._propType = propType;

};

RG.Object.Typed.prototype.getPropType = function() {return this._propType;};
RG.Object.Typed.prototype.getType = function() {return this.type;};

RG.Object.Typed.prototype.setPropType = function(propType) {
    var index = RG.PROP_TYPES.indexOf(propType);
    if (index >= 0) {
        this._propType = propType;
    }
    else {
        RG.err('Object.Typed', 'setPropType',
            'Unknown prop type: |' + propType + '|');
    }
};

RG.Object.Typed.prototype.setType = function(type) {
    this.type = type;
    RG.nullOrUndefError('Object.Typed: setType', 'arg |type|', type);
};

/* This object is used by all locatable objects in the game.  */
class RGObjectLocatable {
    constructor() { // {{{2
        this._x = null;
        this._y = null;
        this._level = null;
    }

    setX(x) {this._x = x; }
    setY(y) {this._y = y; }
    getX() {return this._x;}
    getY() {return this._y;}

    getXY() {
        return [this._x, this._y];
    }

    /* Simple getters/setters for coordinates.*/
    setXY(x, y) {
        this._x = x;
        this._y = y;
    }

    /* Accessing the current cell of object. */
    getCell() {
        return this._level.getMap().getCell(this._x, this._y);
    }

    /* Sets the level of this locatable object.*/
    setLevel(level) {
        this._level = level;
        RG.nullOrUndefError('Object.Locatable: setLevel', 'arg |level|', level);
    }

    /* Unsets the level to null. Throws error if level already null. */
    unsetLevel() {
        if (this._level) {
            this._level = null;
        }
        else {
            RG.err('Object.Locatable', 'unsetLevel',
                'Trying to unset already null level.');
        }
    }

    getLevel() {
        return this._level;
    }

    /* Returns true if object is located at a position on a level.*/
    isLocated() {
        return (this._x !== null) && (this._y !== null) && (this._level !== null);
    }

    /* Returns true if locatables are in same position.*/
    isSamePos(obj) {
        if (this._x !== obj.getX()) {return false;}
        if (this._y !== obj.getY()) {return false;}
        if (this._level !== obj.getLevel()) {return false;}
        return true;
    }
} // }}} Object.Locatable

RG.Object.Locatable = RGObjectLocatable;

/* Object.Ownable moves with its owner. Thus, it's x-y position is
 * determined by the owner. This ensures that
 * for example item coordinates are up-to-date with the carrier.*/
RG.Object.Ownable = function(owner) {
    let _owner = owner;

    this.isSamePos = obj => _owner.isSamePos(obj);

    this.getLevel = () => _owner.getLevel();

    this.setOwner = owner => {
        if (RG.isNullOrUndef([owner])) {
            RG.err('Object.Ownable', 'setOwner', 'Owner cannot be null.');
        }
        else {
            _owner = owner;
        }
    };

    /* Returns the owner of this object.*/
    this.getOwner = () => _owner;

    this.getX = () => {
        if (_owner !== null) {return _owner.getX();}
        return null;
    };

    this.getY = () => {
        if (_owner !== null) {return _owner.getY();}
        return null;
    };

    this.getLevel = () => {
        if (_owner !== null) {return _owner.getLevel();}
        return null;
    };

};

module.exports = RG.Object;
<commit_msg>Removed Object.Typed.<commit_after>
const RG = require('./rg.js');

RG.Object = {};

RG.Object.Defense = function() {
    this._attack = 1;
    this._defense = 1;
    this._protection = 0;
};

RG.Object.Defense.prototype.getAttack = function() {return this._attack;};
RG.Object.Defense.prototype.setAttack = function(attack) {
    this._attack = attack;
};

/* Defense related methods.*/
RG.Object.Defense.prototype.getDefense = function() { return this._defense; };
RG.Object.Defense.prototype.setDefense = function(defense) {
    this._defense = defense;
};

RG.Object.Defense.prototype.getProtection = function() {
    return this._protection;
};
RG.Object.Defense.prototype.setProtection = function(prot) {
    this._protection = prot;
};

RG.Object.Defense.prototype.copy = function(rhs) {
    this.setAttack(rhs.getAttack());
    this.setDefense(rhs.getDefense());
    this.setProtection(rhs.getProtection());
};

RG.Object.Defense.prototype.equals = function(rhs) {
    const res = this.getAttack() === rhs.getAttack() &&
        this.getDefense() === rhs.getDefense() &&
        this.getProtection() === rhs.getProtection();
    return res;
};

RG.Object.Defense.prototype.toJSON = function() {
    const json = {
        setAttack: this.getAttack(),
        setDefense: this.getDefense(),
        setProtection: this.getProtection()
    };
    return json;
};

/* Damage object used in Weapons and other damaging things. */
RG.Object.Damage = function() {
    RG.Object.Defense.call(this);
    let _damageDie = new RG.Die(1, 4, 0);
    let _range = 1;

    /* Attack methods. */
    this.setAttackRange = range => {_range = range;};
    this.getAttackRange = () => _range;

    this.rollDamage = function() {
        if (this.hasOwnProperty('getWeapon')) {
            const weapon = this.getWeapon();
            if (!RG.isNullOrUndef([weapon])) {
                return weapon.rollDamage();
            }
        }
        return _damageDie.roll();
    };

    this.getDamageDie = () => _damageDie;

    this.setDamageDie = dStr => {
        if (typeof dStr === 'string') {
            _damageDie = RG.FACT.createDie(dStr);
        }
        else if (typeof dStr === 'object') {
            _damageDie = dStr;
        }
    };

};
RG.extend2(RG.Object.Damage, RG.Object.Defense);

RG.Object.Damage.prototype.copy = function(rhs) {
    RG.Object.Defense.prototype.copy.call(this, rhs);
    this.setAttackRange(rhs.getAttackRange());
    const die = new RG.Die();
    die.copy(rhs.getDamageDie());
    this.setDamageDie(die);
};

RG.Object.Damage.prototype.equals = function(rhs) {
    var res = RG.Object.Defense.prototype.equals.call(this, rhs);
    if (res) {
        res = this.getDamageDie().equals(rhs.getDamageDie());
        res = res && this.getAttackRange() === rhs.getAttackRange();
    }
    return res;
};

RG.Object.Damage.prototype.toString = function() {
    var msg = ' A: ' + this.getAttack() + ', D: ' + this.getDefense() + ', ';
    msg += 'Dmg: ' + this.getDamageDie().toString();
    msg += ',R:' + this.getAttackRange();
    return msg;
};

RG.Object.Damage.prototype.toJSON = function() {
    var json = RG.Object.Defense.prototype.toJSON.call(this);
    json.setAttackRange = this.getAttackRange();
    json.setDamageDie = this.getDamageDie().toString();
    return json;
};

/* This object is used by all locatable objects in the game.  */
class RGObjectLocatable {
    constructor() { // {{{2
        this._x = null;
        this._y = null;
        this._level = null;
    }

    setX(x) {this._x = x; }
    setY(y) {this._y = y; }
    getX() {return this._x;}
    getY() {return this._y;}

    getXY() {
        return [this._x, this._y];
    }

    /* Simple getters/setters for coordinates.*/
    setXY(x, y) {
        this._x = x;
        this._y = y;
    }

    /* Accessing the current cell of object. */
    getCell() {
        return this._level.getMap().getCell(this._x, this._y);
    }

    /* Sets the level of this locatable object.*/
    setLevel(level) {
        this._level = level;
        RG.nullOrUndefError('Object.Locatable: setLevel', 'arg |level|', level);
    }

    /* Unsets the level to null. Throws error if level already null. */
    unsetLevel() {
        if (this._level) {
            this._level = null;
        }
        else {
            RG.err('Object.Locatable', 'unsetLevel',
                'Trying to unset already null level.');
        }
    }

    getLevel() {
        return this._level;
    }

    /* Returns true if object is located at a position on a level.*/
    isLocated() {
        return (this._x !== null) && (this._y !== null) && (this._level !== null);
    }

    /* Returns true if locatables are in same position.*/
    isSamePos(obj) {
        if (this._x !== obj.getX()) {return false;}
        if (this._y !== obj.getY()) {return false;}
        if (this._level !== obj.getLevel()) {return false;}
        return true;
    }
} // }}} Object.Locatable

RG.Object.Locatable = RGObjectLocatable;

/* Object.Ownable moves with its owner. Thus, it's x-y position is
 * determined by the owner. This ensures that
 * for example item coordinates are up-to-date with the carrier.*/
RG.Object.Ownable = function(owner) {
    let _owner = owner;

    this.isSamePos = obj => _owner.isSamePos(obj);

    this.getLevel = () => _owner.getLevel();

    this.setOwner = owner => {
        if (RG.isNullOrUndef([owner])) {
            RG.err('Object.Ownable', 'setOwner', 'Owner cannot be null.');
        }
        else {
            _owner = owner;
        }
    };

    /* Returns the owner of this object.*/
    this.getOwner = () => _owner;

    this.getX = () => {
        if (_owner !== null) {return _owner.getX();}
        return null;
    };

    this.getY = () => {
        if (_owner !== null) {return _owner.getY();}
        return null;
    };

    this.getLevel = () => {
        if (_owner !== null) {return _owner.getLevel();}
        return null;
    };

};

module.exports = RG.Object;
<|endoftext|>


<commit_before>import { test, SYNTAX_CASES } from '../utils'

import { RuleTester, linter } from 'eslint'
import semver from 'semver'

var ruleTester = new RuleTester()
  , rule = require('rules/export')

ruleTester.run('export', rule, {
  valid: [
    test({ code: 'import "./malformed.js"' }),

    // default
    test({ code: 'var foo = "foo"; export default foo;' }),
    test({ code: 'export var foo = "foo"; export var bar = "bar";'}),
    test({ code: 'export var foo = "foo", bar = "bar";' }),
    test({ code: 'export var { foo, bar } = object;' }),
    test({ code: 'export var [ foo, bar ] = array;' }),
    test({ code: 'export var { foo, bar } = object;' }),
    test({ code: 'export var [ foo, bar ] = array;' }),
    test({ code: 'let foo; export { foo, foo as bar }' }),
    test({ code: 'let bar; export { bar }; export * from "./export-all"' }),
    test({ code: 'export * from "./export-all"' }),
    test({ code: 'export * from "./does-not-exist"' }),

    // #328: "export * from" does not export a default
    test({ code: 'export default foo; export * from "./bar"' }),

    ...SYNTAX_CASES,
  ],

  invalid: [
    // multiple defaults
    // test({
    //   code: 'export default foo; export default bar',
    //   errors: ['Multiple default exports.', 'Multiple default exports.'],
    // }),
    // test({
    //   code: 'export default function foo() {}; ' +
    //              'export default function bar() {}',
    //   errors: ['Multiple default exports.', 'Multiple default exports.'],
    // }),

    // test({
    //   code: 'export function foo() {}; ' +
    //              'export { bar as foo }',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export {foo}; export {foo};',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export {foo}; export {bar as foo};',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var foo = "foo"; export var foo = "bar";',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var foo = "foo", foo = "bar";',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    test({
      code: 'let foo; export { foo }; export * from "./export-all"',
      errors: ['Multiple exports of name \'foo\'.',
               'Multiple exports of name \'foo\'.'],
    }),
    // test({ code: 'export * from "./default-export"'
    //      , errors: [{ message: 'No named exports found in module ' +
    //                            '\'./default-export\'.'
    //                 , type: 'Literal' }] }),

    // note: Espree bump to Acorn 4+ changed this test's error message.
    //       `npm up` first if it's failing.
    test({
      code: 'export * from "./malformed.js"',
      errors: [{
        message: "Parse errors in imported module './malformed.js': 'return' outside of function (1:1)",
        type: 'Literal',
      }],
    }),

    // test({
    //   code: 'export var { foo, bar } = object; export var foo = "bar"',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var { bar: { foo } } = object; export var foo = "bar"',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var [ foo, bar ] = array; export var bar = "baz"',
    //   errors: ['Parsing error: Duplicate export \'bar\''],
    // }),
    // test({
    //   code: 'export var [ foo, /*sparse*/, { bar } ] = array; export var bar = "baz"',
    //   errors: ['Parsing error: Duplicate export \'bar\''],
    // }),

    // #328: "export * from" does not export a default
    test({
      code: 'export * from "./default-export"',
      errors: [`No named exports found in module './default-export'.`],
    }),
  ],
})

context('Typescript', function () {
  // Typescript
  const parsers = ['typescript-eslint-parser']

  if (semver.satisfies(linter.version, '>5.0.0')) {
    parsers.push('@typescript-eslint/parser')
  }

  parsers.forEach((parser) => {
    const parserConfig = {
      parser: parser,
      settings: {
        'import/parsers': { [parser]: ['.ts'] },
        'import/resolver': { 'eslint-import-resolver-typescript': true },
      },
    }

    ruleTester.run('export', rule, {
      valid: [
        test(Object.assign({
          code: `
            export const Foo = 1;
            export type Foo = number;
          `,
        }, parserConfig),
        test(Object.assign({
          code: `
            export const Foo = 1;
            export interface Foo {}
          `,
        }, parserConfig),
      ],
      invalid: [],
    })
  })
})
<commit_msg>[Tests] fix tests from #1319<commit_after>import { test, SYNTAX_CASES } from '../utils'

import { RuleTester, linter } from 'eslint'
import semver from 'semver'

var ruleTester = new RuleTester()
  , rule = require('rules/export')

ruleTester.run('export', rule, {
  valid: [
    test({ code: 'import "./malformed.js"' }),

    // default
    test({ code: 'var foo = "foo"; export default foo;' }),
    test({ code: 'export var foo = "foo"; export var bar = "bar";'}),
    test({ code: 'export var foo = "foo", bar = "bar";' }),
    test({ code: 'export var { foo, bar } = object;' }),
    test({ code: 'export var [ foo, bar ] = array;' }),
    test({ code: 'export var { foo, bar } = object;' }),
    test({ code: 'export var [ foo, bar ] = array;' }),
    test({ code: 'let foo; export { foo, foo as bar }' }),
    test({ code: 'let bar; export { bar }; export * from "./export-all"' }),
    test({ code: 'export * from "./export-all"' }),
    test({ code: 'export * from "./does-not-exist"' }),

    // #328: "export * from" does not export a default
    test({ code: 'export default foo; export * from "./bar"' }),

    ...SYNTAX_CASES,
  ],

  invalid: [
    // multiple defaults
    // test({
    //   code: 'export default foo; export default bar',
    //   errors: ['Multiple default exports.', 'Multiple default exports.'],
    // }),
    // test({
    //   code: 'export default function foo() {}; ' +
    //              'export default function bar() {}',
    //   errors: ['Multiple default exports.', 'Multiple default exports.'],
    // }),

    // test({
    //   code: 'export function foo() {}; ' +
    //              'export { bar as foo }',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export {foo}; export {foo};',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export {foo}; export {bar as foo};',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var foo = "foo"; export var foo = "bar";',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var foo = "foo", foo = "bar";',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    test({
      code: 'let foo; export { foo }; export * from "./export-all"',
      errors: ['Multiple exports of name \'foo\'.',
               'Multiple exports of name \'foo\'.'],
    }),
    // test({ code: 'export * from "./default-export"'
    //      , errors: [{ message: 'No named exports found in module ' +
    //                            '\'./default-export\'.'
    //                 , type: 'Literal' }] }),

    // note: Espree bump to Acorn 4+ changed this test's error message.
    //       `npm up` first if it's failing.
    test({
      code: 'export * from "./malformed.js"',
      errors: [{
        message: "Parse errors in imported module './malformed.js': 'return' outside of function (1:1)",
        type: 'Literal',
      }],
    }),

    // test({
    //   code: 'export var { foo, bar } = object; export var foo = "bar"',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var { bar: { foo } } = object; export var foo = "bar"',
    //   errors: ['Parsing error: Duplicate export \'foo\''],
    // }),
    // test({
    //   code: 'export var [ foo, bar ] = array; export var bar = "baz"',
    //   errors: ['Parsing error: Duplicate export \'bar\''],
    // }),
    // test({
    //   code: 'export var [ foo, /*sparse*/, { bar } ] = array; export var bar = "baz"',
    //   errors: ['Parsing error: Duplicate export \'bar\''],
    // }),

    // #328: "export * from" does not export a default
    test({
      code: 'export * from "./default-export"',
      errors: [`No named exports found in module './default-export'.`],
    }),
  ],
})

context('Typescript', function () {
  // Typescript
  const parsers = ['typescript-eslint-parser']

  if (semver.satisfies(linter.version, '>5.0.0')) {
    parsers.push('@typescript-eslint/parser')
  }

  parsers.forEach((parser) => {
    const parserConfig = {
      parser: parser,
      settings: {
        'import/parsers': { [parser]: ['.ts'] },
        'import/resolver': { 'eslint-import-resolver-typescript': true },
      },
    }

    ruleTester.run('export', rule, {
      valid: [
        test(Object.assign({
          code: `
            export const Foo = 1;
            export type Foo = number;
          `,
        }, parserConfig),
        test(Object.assign({
          code: `
            export const Foo = 1;
            export interface Foo {}
          `,
        }, parserConfig))),
      ],
      invalid: [],
    })
  })
})
<|endoftext|>


<commit_before>"use strict";

(function () {

	function PopUpCtrl ($scope, StorageService) {

		var updateBackgroundBlockList = function (items) {

		}

		// Fetch initial data
		$scope.linkEntities = [];
		StorageService.read(null, function (items) {
			$scope.$apply(function () { // Apply to force digest outside of cycle
				for(var key in items) {
				    $scope.linkEntities.push(items[key]);
				}
				// Update block list
				chrome.extension.getBackgroundPage().BackgroundService.updateBlockList($scope.linkEntities);
			});
		});

		var createUIElement = function (result) {
			$scope.$apply(function () {
				$scope.linkEntities.push(result); // Apply to force digest outside of cycle
			});
		};

		$scope.create = function (inputUrl) {
			var urlExists = function (element) {
				return element.link.toString() == inputUrl.toString();
			};

			// Filter for existing entries
			if (inputUrl && !$scope.linkEntities.some(urlExists)) {
				// Call storage service
				StorageService.create(inputUrl, createUIElement);
			} else {
				// If it already exists, help them find it.
				$scope.query = inputUrl;
			}
		};

		var deleteFromUI = function (id) {
			if (!id) throw "Mising ID parameter. When deleting from UI."
			// Update UI array
			var updateUIArray = function () {
				$scope.linkEntities.forEach(function(item, idx) {
					if ($scope.linkEntities[idx].id == id) {
						$scope.linkEntities.splice(idx, 1);
					}
				});
			};

			$scope.$apply(updateUIArray); // Apply to force digest outside of cycle
		}

		$scope.delete = function (id) {
			StorageService.delete(id, deleteFromUI);
		};
	};

	angular.module("LinkBlockerApp", []);

	angular
		.module("LinkBlockerApp")
		.controller("PopUpCtrl", PopUpCtrl);
})();<commit_msg>Update background block service on CRUD operations.<commit_after>"use strict";

(function () {

	function PopUpCtrl ($scope, StorageService) {

		var updateBackgroundBlockList = function (items) {

		}

		// Fetch initial data
		$scope.linkEntities = [];
		StorageService.read(null, function (items) {
			$scope.$apply(function () { // Apply to force digest outside of cycle
				for(var key in items) {
				    $scope.linkEntities.push(items[key]);
				}

				// Update block list
				chrome.extension.getBackgroundPage().BackgroundService.updateBlockList($scope.linkEntities);
			});
		});

		var createUIElement = function (result) {
			$scope.$apply(function () {
				$scope.linkEntities.push(result); // Apply to force digest outside of cycle

				// Update block list
				chrome.extension.getBackgroundPage().BackgroundService.updateBlockList($scope.linkEntities);
			});
		};

		$scope.create = function (inputUrl) {
			var urlExists = function (element) {
				return element.link.toString() == inputUrl.toString();
			};

			// Filter for existing entries
			if (inputUrl && !$scope.linkEntities.some(urlExists)) {
				// Call storage service
				StorageService.create(inputUrl, createUIElement);
			} else {
				// If it already exists, help them find it.
				$scope.query = inputUrl;
			}
		};

		var deleteFromUI = function (id) {
			if (!id) throw "Mising ID parameter. When deleting from UI."
			// Update UI array
			var updateUIArray = function () {
				$scope.linkEntities.forEach(function(item, idx) {
					if ($scope.linkEntities[idx].id == id) {
						$scope.linkEntities.splice(idx, 1);
					}
				});

				// Update block list
				chrome.extension.getBackgroundPage().BackgroundService.updateBlockList($scope.linkEntities);
			};

			$scope.$apply(updateUIArray); // Apply to force digest outside of cycle
		}

		$scope.delete = function (id) {
			StorageService.delete(id, deleteFromUI);
		};
	};

	angular.module("LinkBlockerApp", []);

	angular
		.module("LinkBlockerApp")
		.controller("PopUpCtrl", PopUpCtrl);
})();<|endoftext|>


<commit_before>context('Web Form', () => {
	before(() => {
		cy.login();
	});

	it('Navigate and Submit a WebForm', () => {
		cy.visit('/update-profile');
		cy.get_field('last_name', 'Data').type('_Test User', {force: true}).wait(200);
		cy.get('.web-form-actions .btn-primary').click();
		cy.wait(500);
		cy.get('.modal.show > .modal-dialog').should('be.visible');
	});

	it('Navigate and Submit a MultiStep WebForm', () => {
		cy.call('frappe.tests.ui_test_helpers.update_webform_to_multistep').then(() => {
			cy.visit('/update-profile-duplicate');
			cy.get_field('last_name', 'Data').type('_Test User', {force: true}).wait(200);
			cy.get('.btn-next').should('be.visible');
			cy.get('.btn-next').click();
			cy.get('.btn-previous').should('be.visible');
			cy.get('.btn-next').should('not.be.visible');
			cy.get('.web-form-actions .btn-primary').click();
			cy.wait(500);
			cy.get('.modal.show > .modal-dialog').should('be.visible');
		});
	});
});
<commit_msg>fix(test): web_form.js<commit_after>context('Web Form', () => {
	before(() => {
		cy.login();
	});

	it('Navigate and Submit a WebForm', () => {
		cy.visit('/update-profile');
		cy.get_field('last_name', 'Data').type('_Test User', {force: true}).wait(200);
		cy.get('.web-form-actions .btn-primary').click();
		cy.wait(5000);
		cy.url().should('include', '/me');
	});

	it('Navigate and Submit a MultiStep WebForm', () => {
		cy.call('frappe.tests.ui_test_helpers.update_webform_to_multistep').then(() => {
			cy.visit('/update-profile-duplicate');
			cy.get_field('last_name', 'Data').type('_Test User', {force: true}).wait(200);
			cy.get('.btn-next').should('be.visible');
			cy.get('.btn-next').click();
			cy.get('.btn-previous').should('be.visible');
			cy.get('.btn-next').should('not.be.visible');
			cy.get('.web-form-actions .btn-primary').click();
			cy.wait(5000);
			cy.url().should('include', '/me');
		});
	});
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var formidable = require('formidable'),
    http = require('http'),
    util = require('util'),
    os = require('os'),
    fs = require('fs'),
    crypto = require('crypto'),
    uploadDir = os.tmpDir() + "/uplodr",
    config = require('./config.js');

if (typeof config.customUploadDir !== 'undefined') uploadDir = config.customUploadDir;

mkdirIfNotExist(uploadDir);

http.createServer(function(req, res) {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    // current date/time of session
    var date = new Date();
    var dateString = '' + date.getFullYear() + twoDigits(date.getMonth()+1) + twoDigits(date.getDate()) + '-' + twoDigits(date.getHours()) + twoDigits(date.getMinutes()) + twoDigits(date.getSeconds()) + '-' + date.getTimezoneOffset();
    var newUploadDir = uploadDir + '/' + dateString + '-' + randomCharacters(5);
    mkdirIfNotExist(newUploadDir);
    // parse a file upload
    var form = new formidable.IncomingForm();
    form.uploadDir = newUploadDir;
    form.parse(req, function(err, fields, files) {
      if (typeof files.upload !== 'undefined') {
        if (files.upload.size !== 0) {
          // metafile, files.upload, "upload" is the name of the input field
          var metafile = files.upload.path + '.txt';
          fs.appendFile(metafile, util.inspect({fields: fields, files: files}), function(err){
            if (err) throw err;
          });
          if (files.upload.name.lastIndexOf('.') > 0) {
            var parts = files.upload.name.split('.');
            var extension = parts.pop();
            if (String(extension).length > 0) {
              var safename = newUploadDir + '/' + parts.join().match(/[a-zA-Z0-9]+/g).join().replace(/,/g,'') + '.' + extension;
            } else {
              var safename = newUploadDir + '/' + parts.join().match(/[a-zA-Z0-9]+/g).join().replace(/,/g,'');
            }
            fs.rename(files.upload.path, safename, function(err){
              if (err) throw err;
            });
          }
        }
      }
      // response to browser
      res.writeHead(200, {'content-type': 'text/plain'});
      res.write('received upload.\n\n');
      // res.end(util.inspect({fields: fields, files: files}));
      res.end();
    });
    return;
  }

  // show a file upload form
  res.writeHead(200, {'content-type': 'text/html'});
  res.end(
    '<form action="/upload" enctype="multipart/form-data" method="post">'+
    '<input type="text" name="title">
'+
    '<input type="file" name="upload">
'+
    '<input type="submit" value="Upload">'+
    '</form>'
  );
}).listen(80);

function mkdirIfNotExist(dir) {
  if (!fs.existsSync(dir)) fs.mkdirSync(dir);
  if (!fs.existsSync(dir)) {
    return false;
  } else {
    return fs.statSync(dir).isDirectory();
  }
}

function twoDigits(num) {
  if (Number(num) < 10) {
    return '0' + Number(num);
  } else {
    return num;
  }
}

function randomCharacters (count, characters) {
  characters = characters || "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var result = new Array(count),
      randomByte = crypto.randomBytes(count);
  for (var i = 0; i < count; i++) {
    result[i] = characters[randomByte[i] % characters.length]
  };
  return result.join('');
}
<commit_msg>use UTC to avoid DST<commit_after>#!/usr/bin/env node

var formidable = require('formidable'),
    http = require('http'),
    util = require('util'),
    os = require('os'),
    fs = require('fs'),
    crypto = require('crypto'),
    uploadDir = os.tmpDir() + "/uplodr",
    config = require('./config.js');

if (typeof config.customUploadDir !== 'undefined') uploadDir = config.customUploadDir;

mkdirIfNotExist(uploadDir);

http.createServer(function(req, res) {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    // current date/time of session, use UTC because avoid DST
    var date = new Date();
    var dateString = '' + date.getUTCFullYear() + twoDigits(date.getUTCMonth()+1) + twoDigits(date.getUTCDate()) + '-' + twoDigits(date.getUTCHours()) + twoDigits(date.getUTCMinutes()) + twoDigits(date.getUTCSeconds());
    var newUploadDir = uploadDir + '/' + dateString + '-' + randomCharacters(5);
    mkdirIfNotExist(newUploadDir);
    // parse a file upload
    var form = new formidable.IncomingForm();
    form.uploadDir = newUploadDir;
    form.parse(req, function(err, fields, files) {
      if (typeof files.upload !== 'undefined') {
        if (files.upload.size !== 0) {
          // metafile, files.upload, "upload" is the name of the input field
          var metafile = files.upload.path + '.txt';
          fs.appendFile(metafile, util.inspect({fields: fields, files: files}), function(err){
            if (err) throw err;
          });
          console.log('uplodr: new %s', metafile);
          if (files.upload.name.lastIndexOf('.') > 0) {
            var parts = files.upload.name.split('.');
            var extension = parts.pop();
            if (String(extension).length > 0) {
              var safename = newUploadDir + '/' + parts.join().match(/[a-zA-Z0-9]+/g).join().replace(/,/g,'') + '.' + extension;
            } else {
              var safename = newUploadDir + '/' + parts.join().match(/[a-zA-Z0-9]+/g).join().replace(/,/g,'');
            }
            fs.rename(files.upload.path, safename, function(err){
              if (err) throw err;
            });
          }
        }
      }
      // response to browser
      res.writeHead(200, {'content-type': 'text/plain'});
      res.write('received upload.\n\n');
      // res.end(util.inspect({fields: fields, files: files}));
      res.end();
    });
    return;
  }

  // show a file upload form
  res.writeHead(200, {'content-type': 'text/html'});
  res.end(
    '<form action="/upload" enctype="multipart/form-data" method="post">'+
    '<input type="text" name="title">
'+
    '<input type="file" name="upload">
'+
    '<input type="submit" value="Upload">'+
    '</form>'
  );
}).listen(80);

function mkdirIfNotExist(dir) {
  if (!fs.existsSync(dir)) fs.mkdirSync(dir);
  if (!fs.existsSync(dir)) {
    return false;
  } else {
    return fs.statSync(dir).isDirectory();
  }
}

function twoDigits(num) {
  if (Number(num) < 10) {
    return '0' + Number(num);
  } else {
    return num;
  }
}

function randomCharacters (count, characters) {
  characters = characters || "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var result = new Array(count),
      randomByte = crypto.randomBytes(count);
  for (var i = 0; i < count; i++) {
    result[i] = characters[randomByte[i] % characters.length]
  };
  return result.join('');
}
<|endoftext|>


<commit_before>var assert = require('chai').assert;
var webdriverio = require('webdriverio');
var express = require('express');

var options = {
  desiredCapabilities: {
    browserName: 'chrome',
    chromeOptions: {
      args: [
         "--load-extension=./"
       ]
    }
  }
};

var client = webdriverio.remote(options);
var helpers = require('../webdriver-helpers')(client);

var extensionId;
var backendServer;

describe('Extension to web page integration', function(){
  this.timeout(10000)

  before(function(done){
    client.init()
      .timeouts('script', 60000)
      .then(function(){
      // Get the extension ID
      helpers.getExtensionId(function(err, theExtensionId){
        extensionId = theExtensionId;
        done(err);
      });
    });
  });

  after(function(done){
    client.end();
    done();
  })

  describe('Externally connectable', function(){
    before(function(done){
      // Spin up the local server listsening on 'http://third.second.first'
      app = express();

      app.use(express.static('test/fixtures/embed/'));

      app.get('/', function (req, res) {
        res.send('Hello World!');
      });

      backendServer = app.listen(3000, function(){
        done()
      });
    })

    after(function(done){
      client.end()

      backendServer.close(function(){
        done();
      })
    });

    describe('When the page is accessed on a third level domain',function(){
      describe('When I go to the page where the extension should be connectable',function(){
        describe('And I send a message to the extension', function(){
          it('The page JS should get an answer', function(done){
            fn = function(extId, callback){
              chrome.runtime.sendMessage(extId, "Foo Bar", function(response){
                callback(response)
              });
            }

            client
              .url('http://third.second.first:3000/')
              .then(function(){
                helpers.executeAsync([fn, extensionId], function(err, result){
                  assert.equal(result.value, "BooBoo")
                  done()
                })
              });
          });
        });
      });
    });

    describe('When the page is accessed on a fourth level domain',function(){
      describe('When I go to the page where the extension should be connectable',function(){
        describe('And I send a message to the extension', function(){
          it('The page JS should get an answer', function(done){
            fn = function(extId, callback){
              chrome.runtime.sendMessage(extId, "Foo Bar", function(response){
                callback(response)
              });
            }

            client
              .url('http://fourth.third.second.first:3000/')
              .then(function(){
                helpers.executeAsync([fn, extensionId], function(err, result){
                  assert.equal(result.value, "BooBoo")
                  done()
                })
              });
          });
        });
      });
    });

    describe('When the page is accessed via iframe from to third level domain via completely different domain', function(){
      var iframeBackend
      before(function(done){
        // Spin up the local server listsening on 'http://third.second.first'
        app = express();

        app.use(express.static('test/fixtures/embed/'));

        app.get('/', function (req, res) {
          res.send('Hello World!');
        });

        iframeBackend = app.listen(3001, function(){
          done()
        });
      });

      after(function(done){
        client.end()

        iframeBackend.close(function(){
          done();
        })
      });
      describe('When I go to the page where the connectable page is embedded', function(){
        describe('And I send interact with the extension', function(){
          it("Should have the data returned from the extension", function(done){

            client
              .url('http://localhost:3001/embed.html')
              .waitForExist('iframe[name=embed]')
              .frame("embed")
              .then(function(){
                fn = function(injectedExtId){
                  extId = injectedExtId;
                }

                helpers.execute([fn, extensionId], function(){
                  client
                    .click('#interaction')
                    .waitForExist('#extension-data')
                    .getText("#extension-data")
                    .then(function(text){
                      console.log('preassertion');
                      assert.equal(text,"BooBoo");
                      done();
                    }).call();
                });

            });
          });
        });
      });
    });
  });
});<commit_msg>Rename page integration file<commit_after><|endoftext|>


<commit_before>/*jslint node: true */
'use strict';

	// Gulp
var gulp            = require('gulp'),
	plugins         = require('gulp-load-plugins')({
        rename: {
            'gulp-compile-handlebars' : 'handlebars',
            'gulp-sass-generate-contents' : 'sgc',
            'gulp-minify-css' : 'minifyCss',
            'gulp-if' : 'gulpif'
        }
    }),

	// Utilities
	argv             = require('yargs').argv,
	runSeq           = require('run-sequence'),
    browserSync      = require('browser-sync'),

	// CSS
	autoprefixer     = require('autoprefixer-core'),

	// Images
	pngquant         = require('imagemin-pngquant'),

	// Configuration
	config           = require('./_config/project.json'),
	templateDataJson = require('./_config/templateData.json'),
	templateHelpers  = require('./_config/templateHelpers.js')(),
	jshintConfig     = require('./_config/jshint.json'),
	creds            = require('./_config/creds.json'),
	itcss            = require('./_config/itcss'),
	destStyles       = config.src + '/' + config.dirs.styles;

/* ============================================================ *\
	SCRIPTS JS / lint, concat and minify scripts
\* ============================================================ */

gulp.task('scripts', function(){
	return gulp.src([config.src + '/' + config.dirs.scripts + '/**/*.js'])
		.pipe(plugins.gulpif(argv.prod, plugins.jshint(jshintConfig))) //Default only
		.pipe(plugins.concat('bundle.js'))
		.pipe(plugins.gulpif(argv.prod, plugins.uglify())) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.scripts));
});

/* ============================================================ *\
	GENERATE SASS IMPORTS AND
\* ============================================================ */

gulp.task('sass-generate-contents', function () {
	return gulp.src(itcss())
	.pipe(plugins.sgc(destStyles + '/main.scss', creds))
	.pipe(gulp.dest(destStyles));
});

/* ============================================================ *\
	STYLES / SCSS
\* ============================================================ */

gulp.task('sass', ['sprites'],function () {
	return gulp.src(destStyles + '/main.scss')
		.pipe(plugins.gulpif(!argv.prod, plugins.sourcemaps.init())) //Default only
		.pipe(plugins.sass({ errLogToConsole: true, includePaths: [config.dirs.components], outputStyle: 'compact' }))
		.pipe(plugins.postcss([autoprefixer({ browsers: ['> 5%', 'Android 3'] })]))
		.pipe(plugins.pixrem(config.pixelBase))
		.pipe(plugins.gulpif(!argv.prod, plugins.sourcemaps.write('.'))) //Default only
		.pipe(plugins.pixrem(config.pixelBase))
		.pipe(plugins.gulpif(argv.prod, plugins.minifyCss())) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.styles));
});

/* ============================================================ *\
	IMAGES / minify images
\* ============================================================ */

gulp.task('imagemin', function () {
	return gulp.src(config.src + '/' + config.dirs.images + '/**/*')
		.pipe(plugins.gulpif(argv.prod, plugins.imagemin({
			progressive: true,
			svgoPlugins: [{removeViewBox: false}],
			use: [pngquant()]
		}))) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.images));
});

gulp.task('svgmin', function () {
    return gulp.src(config.src + '/' + config.dirs.images + '/**/*.svg')
        .pipe(plugins.svgmin({
            plugins: [{
                removeDimensions: true
            }, {
                removeTitle: true
            }]
        }))
        .pipe(gulp.dest(config.src + '/' + config.dirs.images));
});

/* ============================================================ *\
	MOVE / Copy files
\* ============================================================ */

gulp.task('copy:fonts', function(){
	return gulp.src([config.src + '/' + config.dirs.fonts + '/**/*'])
		.pipe(gulp.dest(config.dest + '/' + config.dirs.fonts));
})

gulp.task('copy', function(){
	return gulp.src(['!' + config.dest + '/styles', '!' + config.dest + '/styles/*.map', config.dest + '/**/*'])
		.pipe(gulp.dest(config.build));
})

/* ============================================================ *\
	PACKAGE THE FOLDER UP
\* ============================================================ */

gulp.task('package-release', function () {

	var d = new Date();
	var packageName = creds.packageName + '' + d.getDay() + '.' + d.getMonth() + '.' + d.getFullYear() + '_' + d.getHours() + '.' + d.getMinutes();

	return gulp.src('build/**/*')
		.pipe(plugins.zip(packageName + '.zip'))
		.pipe(gulp.dest('release'));
});

/* ============================================================ *\
	COMPILE TEMPLATES / HTML
\* ============================================================ */

gulp.task('compile-html', function () {
	var templateData = {
		data: templateDataJson
	},

	options = {
		batch : ['./views/_partials'],
		helpers: templateHelpers
	}

	return gulp.src(['./views/*.hbs'])
		.pipe(plugins.handlebars(templateData, options))
		.pipe(plugins.rename({extname: '.html'}))
		.pipe(gulp.dest('build'));
});

/* ============================================================ *\
    SPRITES
\* ============================================================ */

gulp.task('sprites', function() {
    return gulp.src(config.src + '/' + config.dirs.images + '/**/*.svg')
        .pipe(plugins.svgSpritesheet({
            cssPathNoSvg: '../' + config.dirs.images + '/sprite.png',
            cssPathSvg: '../' + config.dirs.images + '/sprite.svg',
            padding: 5,
            pixelBase: config.pixelBaseNoUnit,
            positioning: 'packed',
            templateSrc: config.src + '/svg-sprite-sass.tpl',
            templateDest: destStyles + '/_tools/_tools.sprites.scss',
            units: 'em'
        }))
        .pipe(gulp.dest(config.dest + '/' + config.dirs.images + '/sprite.svg'))
        .pipe(plugins.svg2png())
        .pipe(gulp.dest(config.dest + '/' + config.dirs.images + '/sprite.png'));
});

/* ============================================================ *\
    LOCAL TESTING
\* ============================================================ */

gulp.task('browser-sync', function() {
    browserSync.init(null, {
        proxy: "http://localhost:3001",
        files: [config.dest + '/' +  '**/*.*'],
        browser: "google chrome",
        port: 7000,
        ui: {
            port: 7001
        }
    }, function browserSyncCallback() {
        console.log('browser-sync ready, listening on port: 7000')
    });
});

gulp.task('localServer', function(cb) {

    var started = false;

    //Reload website.js if templateData file changes (among other files)
    return plugins.nodemon({
        script: 'website.js',
        ext: 'js json'
    }).on('start', function() {
        if (!started) {
            cb();
            started = true;
        }
    });
});

/* ============================================================ *\
    MAIN TASKS
\* ============================================================ */

gulp.task('watch:sass', function () {
	plugins.gulpif(!argv.prod, gulp.watch([config.src + '/' + config.dirs.styles + '/**/*.scss', config.dirs.components + '/**/*.scss'], ['sass']));
});
gulp.task('watch:js', function () {
	plugins.gulpif(!argv.prod, gulp.watch([config.src + '/' + config.dirs.scripts + '/**/*.js', config.dirs.components + '/**/*.js'], ['scripts']));
});
gulp.task('watch', function (cb) {
	runSeq(['watch:sass', 'watch:js'], cb);
});

gulp.task('build', function (cb) {
	runSeq(['default'], ['copy'], ['compile-html'],  cb);
});

gulp.task('release', function (cb) {
	runSeq(['build'], ['package-release'],  cb);
});

gulp.task('serve', function(cb) {
    runSeq(['localServer'], ['browser-sync'], cb);
});

gulp.task('default', function (cb) {
	runSeq(['sass-generate-contents'],['sass', 'scripts', 'copy:fonts', 'imagemin'], cb);
});
<commit_msg>refactor: Add config directory string into it's own variable<commit_after>/*jslint node: true */
'use strict';

	// Gulp
var gulp            = require('gulp'),
	plugins         = require('gulp-load-plugins')({
        rename: {
            'gulp-compile-handlebars' : 'handlebars',
            'gulp-sass-generate-contents' : 'sgc',
            'gulp-minify-css' : 'minifyCss',
            'gulp-if' : 'gulpif'
        }
    }),

	// Utilities
	argv             = require('yargs').argv,
	runSeq           = require('run-sequence'),
    browserSync      = require('browser-sync'),

	// CSS
	autoprefixer     = require('autoprefixer-core'),

	// Images
	pngquant         = require('imagemin-pngquant'),

	// Configuration
    configDirectory = './_config/',
	config           = require(configDirectory + 'project.json'),
	templateDataJson = require(configDirectory + 'templateData.json'),
	templateHelpers  = require(configDirectory + 'templateHelpers.js')(),
	jshintConfig     = require(configDirectory + 'jshint.json'),
	creds            = require(configDirectory + 'creds.json'),
	itcss            = require(configDirectory + 'itcss'),
	destStyles       = config.src + '/' + config.dirs.styles;

/* ============================================================ *\
	SCRIPTS JS / lint, concat and minify scripts
\* ============================================================ */

gulp.task('scripts', function(){
	return gulp.src([config.src + '/' + config.dirs.scripts + '/**/*.js'])
		.pipe(plugins.gulpif(argv.prod, plugins.jshint(jshintConfig))) //Default only
		.pipe(plugins.concat('bundle.js'))
		.pipe(plugins.gulpif(argv.prod, plugins.uglify())) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.scripts));
});

/* ============================================================ *\
	GENERATE SASS IMPORTS AND
\* ============================================================ */

gulp.task('sass-generate-contents', function () {
	return gulp.src(itcss())
	.pipe(plugins.sgc(destStyles + '/main.scss', creds))
	.pipe(gulp.dest(destStyles));
});

/* ============================================================ *\
	STYLES / SCSS
\* ============================================================ */

gulp.task('sass', ['sprites'],function () {
	return gulp.src(destStyles + '/main.scss')
		.pipe(plugins.gulpif(!argv.prod, plugins.sourcemaps.init())) //Default only
		.pipe(plugins.sass({ errLogToConsole: true, includePaths: [config.dirs.components], outputStyle: 'compact' }))
		.pipe(plugins.postcss([autoprefixer({ browsers: ['> 5%', 'Android 3'] })]))
		.pipe(plugins.pixrem(config.pixelBase))
		.pipe(plugins.gulpif(!argv.prod, plugins.sourcemaps.write('.'))) //Default only
		.pipe(plugins.pixrem(config.pixelBase))
		.pipe(plugins.gulpif(argv.prod, plugins.minifyCss())) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.styles));
});

/* ============================================================ *\
	IMAGES / minify images
\* ============================================================ */

gulp.task('imagemin', function () {
	return gulp.src(config.src + '/' + config.dirs.images + '/**/*')
		.pipe(plugins.gulpif(argv.prod, plugins.imagemin({
			progressive: true,
			svgoPlugins: [{removeViewBox: false}],
			use: [pngquant()]
		}))) //Production only
		.pipe(gulp.dest(config.dest + '/' + config.dirs.images));
});

gulp.task('svgmin', function () {
    return gulp.src(config.src + '/' + config.dirs.images + '/**/*.svg')
        .pipe(plugins.svgmin({
            plugins: [{
                removeDimensions: true
            }, {
                removeTitle: true
            }]
        }))
        .pipe(gulp.dest(config.src + '/' + config.dirs.images));
});

/* ============================================================ *\
	MOVE / Copy files
\* ============================================================ */

gulp.task('copy:fonts', function(){
	return gulp.src([config.src + '/' + config.dirs.fonts + '/**/*'])
		.pipe(gulp.dest(config.dest + '/' + config.dirs.fonts));
})

gulp.task('copy', function(){
	return gulp.src(['!' + config.dest + '/styles', '!' + config.dest + '/styles/*.map', config.dest + '/**/*'])
		.pipe(gulp.dest(config.build));
})

/* ============================================================ *\
	PACKAGE THE FOLDER UP
\* ============================================================ */

gulp.task('package-release', function () {

	var d = new Date();
	var packageName = creds.packageName + '' + d.getDay() + '.' + d.getMonth() + '.' + d.getFullYear() + '_' + d.getHours() + '.' + d.getMinutes();

	return gulp.src('build/**/*')
		.pipe(plugins.zip(packageName + '.zip'))
		.pipe(gulp.dest('release'));
});

/* ============================================================ *\
	COMPILE TEMPLATES / HTML
\* ============================================================ */

gulp.task('compile-html', function () {
	var templateData = {
		data: templateDataJson
	},

	options = {
		batch : ['./views/_partials'],
		helpers: templateHelpers
	}

	return gulp.src(['./views/*.hbs'])
		.pipe(plugins.handlebars(templateData, options))
		.pipe(plugins.rename({extname: '.html'}))
		.pipe(gulp.dest('build'));
});

/* ============================================================ *\
    SPRITES
\* ============================================================ */

gulp.task('sprites', function() {
    return gulp.src(config.src + '/' + config.dirs.images + '/**/*.svg')
        .pipe(plugins.svgSpritesheet({
            cssPathNoSvg: '../' + config.dirs.images + '/sprite.png',
            cssPathSvg: '../' + config.dirs.images + '/sprite.svg',
            padding: 5,
            pixelBase: config.pixelBaseNoUnit,
            positioning: 'packed',
            templateSrc: config.src + '/svg-sprite-sass.tpl',
            templateDest: destStyles + '/_tools/_tools.sprites.scss',
            units: 'em'
        }))
        .pipe(gulp.dest(config.dest + '/' + config.dirs.images + '/sprite.svg'))
        .pipe(plugins.svg2png())
        .pipe(gulp.dest(config.dest + '/' + config.dirs.images + '/sprite.png'));
});

/* ============================================================ *\
    LOCAL TESTING
\* ============================================================ */

gulp.task('browser-sync', function() {
    browserSync.init(null, {
        proxy: "http://localhost:3001",
        files: [config.dest + '/' +  '**/*.*'],
        browser: "google chrome",
        port: 7000,
        ui: {
            port: 7001
        }
    }, function browserSyncCallback() {
        console.log('browser-sync ready, listening on port: 7000')
    });
});

gulp.task('localServer', function(cb) {

    var started = false;

    //Reload website.js if templateData file changes (among other files)
    return plugins.nodemon({
        script: 'website.js',
        ext: 'js json'
    }).on('start', function() {
        if (!started) {
            cb();
            started = true;
        }
    });
});

/* ============================================================ *\
    MAIN TASKS
\* ============================================================ */

gulp.task('watch:sass', function () {
	plugins.gulpif(!argv.prod, gulp.watch([config.src + '/' + config.dirs.styles + '/**/*.scss', config.dirs.components + '/**/*.scss'], ['sass']));
});
gulp.task('watch:js', function () {
	plugins.gulpif(!argv.prod, gulp.watch([config.src + '/' + config.dirs.scripts + '/**/*.js', config.dirs.components + '/**/*.js'], ['scripts']));
});
gulp.task('watch', function (cb) {
	runSeq(['watch:sass', 'watch:js'], cb);
});

gulp.task('build', function (cb) {
	runSeq(['default'], ['copy'], ['compile-html'],  cb);
});

gulp.task('release', function (cb) {
	runSeq(['build'], ['package-release'],  cb);
});

gulp.task('serve', function(cb) {
    runSeq(['localServer'], ['browser-sync'], cb);
});

gulp.task('default', function (cb) {
	runSeq(['sass-generate-contents'],['sass', 'scripts', 'copy:fonts', 'imagemin'], cb);
});
<|endoftext|>