<commit_before>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = [];
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {
    var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

    var icon;

    if(markerImg[crime.category]){
      icon = iconPath + markerImg[crime.category];
    } else {
      icon = iconPath + markerImg.DEFAULT;
    }

    markers.push (new google.maps.Marker({
      position: latlng,
      animation: google.maps.Animation.DROP,
      title: crime.category,
      icon: icon,
      map: map
    }));
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      for (var i = 0; i < markers.length; i++){
        var cat = markers[i].title;
        if (filter === 'violent') {
          // check category against isViolent, if isViolent is false, hide it
          if(!isViolent[cat]) {
            markers[i].setMap(null);
          } else {
            // it shouldn't be filtered out
            markers[i].setMap(map);
          }
        } else {
          // filter is non-violent, check for the opposite
          if(isViolent[cat]) {
            markers[i].setMap(null);
          } else {
            markers[i].setMap(map);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['violent', 'non-violent'];

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng
    googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
  };

  $scope.filterBy = function (filterArg) {
    googleMaps.filterBy(filterArg);
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<commit_msg>Removes markers before adding new ones, includes removeMarkers method<commit_after>angular.module('sfSense', ['ionic'])

.factory('googleMaps', function(){
  // OVERVIEW
  // 1. setup map options
  // 2. create map
  // 3. get data for crime lat and lng
  // 4. create markers
  // 5. add markers to map
  var map;
  var markers = [];
  var isViolent = {
    'ASSAULT': true,
    'NON-CRIMINAL': false,
    'OTHER OFFENSES': false,
    'ROBBERY': true,
    'LARCENY/THEFT': false,
    'VANDALISM': false,
    'BURGLARY': false,
    'VEHICLE THEFT': false,
    'FRAUD': false,
    'DRUNKENNESS': false,
    'WARRANTS': false,
    'TRESPASS': false,
    'KIDNAPPING': true,
    'SEX OFFENSES': true,
    'WEAPON LAWS': true,
    'DRUG/NARCOTIC': false,
    'FORGERY/COUNTERFEITING': false,
    'MISSING PERSON': false,
    'LIQUOR LAWS': false,
    'BAD CHECKS': false,
    'RUNAWAY': false,
    'EMBEZZLEMENT': false
  };

  var iconPath = '../www/img/icons/';

  // TODO: add marker img for each category
  var markerImg = {
    'BURGLARY': 'robbery.png',
    'LARCENY/THEFT': 'theft.png',
    'ASSAULT': 'robbery.png',
    'MISSING PERSON': 'missing.png',
    'DEFAULT': 'blast.png'
  };

  var createMarker = function(crime) {
    var latlng = new google.maps.LatLng(crime.latitude,crime.longitude);

    var icon;

    if(markerImg[crime.category]){
      icon = iconPath + markerImg[crime.category];
    } else {
      icon = iconPath + markerImg.DEFAULT;
    }

    markers.push (new google.maps.Marker({
      position: latlng,
      animation: google.maps.Animation.DROP,
      title: crime.category,
      icon: icon,
      map: map
    }));
  };

  return {

    // Add in google maps functions here

    createMap: function(lat, lng){
      var mapOptions = {
        center: new google.maps.LatLng(lat, lng),
        zoom: 17
      };

      map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
    },

    // CreateMap is not invoked yet so we define addListener to add the event listener
    // Once the map has been created, call addListener
    // Moving method outside of the create call allows access to other services in googleMaps
    // There will only be one map variable so accept only the event and function
    addListener: function(event, func) {
      google.maps.event.addListener(map, event, func);
    },

    createMarkers: function(crimes) {
      for(var i = 0; i < crimes.length; i++){
        createMarker(crimes[i]);
      }
    },

    removeMarkers: function() {
      // first hide all the markers by setting map to null
      for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(null);
      }
      // we no longer want access to the markers so remove them
      markers = [];
    },

    moveTo: function(lat, lng){
      var latlng = new google.maps.LatLng(lat,lng);
      map.panTo(latlng);
    },

    getCenter: function() {
      // returns latlng object with lat() and lng() methods
      return map.getCenter();
    },

    searchLocByAddress: function(address, cb) {
      var city = 'san francisco';
      var re = RegExp(city, 'i');

      if(!re.exec(address)){
        address = address + ' ' + city;
      }

      geocoder = new google.maps.Geocoder();

      geocoder.geocode( {'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          map.setCenter(results[0].geometry.location);

          cb(results[0].geometry.location.k, results[0].geometry.location.A);

        } else {
          navigator.notification.alert('Error with find location: ' + status);
        }
      });
    },

    searchLoc: function(lat, lng, cb){
      var latlng = new google.maps.LatLng(lat,lng);
      map.setCenter(latlng);
      cb(lat, lng);
    },

    filterBy: function(filter){
      for (var i = 0; i < markers.length; i++){
        var cat = markers[i].title;
        if (filter === 'violent') {
          // check category against isViolent, if isViolent is false, hide it
          if(!isViolent[cat]) {
            markers[i].setMap(null);
          } else {
            // it shouldn't be filtered out
            markers[i].setMap(map);
          }
        } else {
          // filter is non-violent, check for the opposite
          if(isViolent[cat]) {
            markers[i].setMap(null);
          } else {
            markers[i].setMap(map);
          }
        }
      }
    }
  };
})

.controller('MapCtrl', function($scope, $http, googleMaps){

  $scope.filters = ['violent', 'non-violent'];

  var init = function() {
    // SF center lat and lng
    var lat = 37.783522;
    var lng = -122.408964;

    googleMaps.createMap(lat, lng);

    // After map has been created, add listeners here
    googleMaps.addListener('dragend', function(){
      // get the lng and lat and call getCrimes with them
      var newCenter = googleMaps.getCenter();
      googleMaps.removeMarkers();
      $scope.getCrimes(newCenter.lat(), newCenter.lng());
    });
  };

  $scope.gpsSearchCrime = function(){

    var onSuccess = function(pos){
      var lat = pos.coords.latitude;
      var lng = pos.coords.longitude;
      googleMaps.searchLoc(lat, lng, $scope.getCrimes);
    };

    var onError = function(error) {
      navigator.notification.alert('Code: ' + error.code + '\n' + 'Message:' + error.message);
    };

    navigator.geolocation.getCurrentPosition(onSuccess, onError);
  };

  $scope.getCrimes = function(lat, lng){

    var url = "http://sf-sense-server.herokuapp.com/near?longitude=" + lng + "&latitude="+ lat + "&distance=0.3";

    $http({
      url: url,
      dataType: 'json',
      method: "GET"
    }).success(function(response){
      googleMaps.createMarkers(response);
    }).error(function(error){
      navigator.notification.alert('There was an error: ' + error);
    });
  };

  $scope.searchCrime = function() {
    // $scope.mapSearch is a street address
    // on success, calls getCrimes with the lat/lng
    googleMaps.searchLocByAddress($scope.mapSearch, $scope.getCrimes);
  };

  $scope.filterBy = function (filterArg) {
    googleMaps.filterBy(filterArg);
  };

  init();
})

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
});

<|endoftext|>


<commit_before>function camxes_preprocessing(input) {
	if (!(typeof input.valueOf() === 'string'))
		return "ERROR: Wrong input type.";
	input = input.replace(/’/gm,"'");
	input = input.replace(/([0-9])\.([0-9])/gm,"$1 pi $2");
	input = input.replace(/0/gm,"no");
	input = input.replace(/1/gm,"pa");
	input = input.replace(/2/gm,"re");
	input = input.replace(/3/gm,"ci");
	input = input.replace(/4/gm,"vo");
	input = input.replace(/5/gm,"mu");
	input = input.replace(/6/gm,"xa");
	input = input.replace(/7/gm,"ze");
	input = input.replace(/8/gm,"bi");
	input = input.replace(/9/gm,"so");
	// --- //
	input = input.replace(/[áàâä]/g,"A");
	input = input.replace(/[éèêë]/g,"E");
	input = input.replace(/[íìîïĭị]/g,"I");
	input = input.replace(/[óòôö]/g,"O");
	input = input.replace(/[úùûüŭụw]/g,"U");
	input = input.replace(/[ýỳŷÿ]/g,"Y");
	// --- //
	input = input.replace(/sh/igm,"c");
	input = input.replace(/zh/igm,"j");
	input = input.replace(/ch/igm,"tc");
	input = input.replace(/kh/igm,"x");
	// --- //
	input = input.replace(/ʃ/igm,"c");
	input = input.replace(/ʒ/igm,"j");
	input = input.replace(/ɛ/gm,"e");
	input = input.replace(/[Ɛɛ́ɛ̀ɛ̂ɛ̈]/gm,"E");
        input = input.replace(/ə/igm,"y");
        input = input.replace(/ŋ/igm,"ng");
	// --- //
	var a = {"Ё":"IO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"C","Щ":"C","З":"Z","Х":"X","Ъ":"Y","Ь":"'","ё":"io","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"c","щ":"c","з":"z","х":"x","ъ":"y","ь":"'","Ф":"F","Ы":"Y","В":"V","А":"a","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"J","Э":"E","ф":"f","ы":"y","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"j","э":"e","Я":"IA","Ч":"TC","С":"S","М":"M","И":"I","Т":"T","Б":"B","Ю":"IU","я":"ia","ч":"tc","с":"s","м":"m","и":"i","т":"t","б":"b","ю":"iu"};
	function transliterate(word){
  	return word.split('').map(function (char) {
    return a[char] || char;
  	}).join("");
	}
	input = transliterate(input);
	// --- //
	input = input.replace(/\(|\)|«|»|—|:/gm,"");
	return input;
}

module.exports.preprocessing = camxes_preprocessing;

<commit_msg>Preproc: allowing <ı> (dotless i) as a synonym to <i>.<commit_after>function camxes_preprocessing(input) {
	if (!(typeof input.valueOf() === 'string'))
		return "ERROR: Wrong input type.";
	input = input.replace(/’/gm,"'");
	input = input.replace(/([0-9])\.([0-9])/gm,"$1 pi $2");
	input = input.replace(/0/gm,"no");
	input = input.replace(/1/gm,"pa");
	input = input.replace(/2/gm,"re");
	input = input.replace(/3/gm,"ci");
	input = input.replace(/4/gm,"vo");
	input = input.replace(/5/gm,"mu");
	input = input.replace(/6/gm,"xa");
	input = input.replace(/7/gm,"ze");
	input = input.replace(/8/gm,"bi");
	input = input.replace(/9/gm,"so");
	// --- //
	input = input.replace(/[áàâä]/g,"A");
	input = input.replace(/[éèêë]/g,"E");
	input = input.replace(/[íìîïĭị]/g,"I");
	input = input.replace(/[óòôö]/g,"O");
	input = input.replace(/[úùûüŭụw]/g,"U");
	input = input.replace(/[ýỳŷÿ]/g,"Y");
	// --- //
	input = input.replace(/sh/igm,"c");
	input = input.replace(/zh/igm,"j");
	input = input.replace(/ch/igm,"tc");
	input = input.replace(/kh/igm,"x");
	// --- //
	input = input.replace(/ı/igm,"i");
	input = input.replace(/ʃ/igm,"c");
	input = input.replace(/ʒ/igm,"j");
	input = input.replace(/ɛ/gm,"e");
	input = input.replace(/[Ɛɛ́ɛ̀ɛ̂ɛ̈]/gm,"E");
        input = input.replace(/ə/igm,"y");
        input = input.replace(/ŋ/igm,"ng");
	// --- //
	var a = {"Ё":"IO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"C","Щ":"C","З":"Z","Х":"X","Ъ":"Y","Ь":"'","ё":"io","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"c","щ":"c","з":"z","х":"x","ъ":"y","ь":"'","Ф":"F","Ы":"Y","В":"V","А":"a","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"J","Э":"E","ф":"f","ы":"y","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"j","э":"e","Я":"IA","Ч":"TC","С":"S","М":"M","И":"I","Т":"T","Б":"B","Ю":"IU","я":"ia","ч":"tc","с":"s","м":"m","и":"i","т":"t","б":"b","ю":"iu"};
	function transliterate(word){
  	return word.split('').map(function (char) {
    return a[char] || char;
  	}).join("");
	}
	input = transliterate(input);
	// --- //
	input = input.replace(/\(|\)|«|»|—|:/gm,"");
	return input;
}

module.exports.preprocessing = camxes_preprocessing;

<|endoftext|>


<commit_before>import ContractAddress from "../fixtures/contractAddress.js";
import ContractStructure from "../fixtures/contractStructure.js";
import web3 from "web3";
import moment from "moment";
import Q from "q";
import PubSub from "pubsub-js"

web3.eth.getBalancePromise = Q.denodeify(web3.eth.getBalance);
web3.eth.getCodePromise = Q.denodeify(web3.eth.getCode);
web3.eth.getBlockPromise = Q.denodeify(web3.eth.getBlock);

class EthClient {
    constructor() {
        let url = null;
        if (window.localStorage && window.localStorage.getItem('rpc_url')) {
            url = window.localStorage.getItem('rpc_url');
        }
        try {
            this.setJsonRPCUrl(url || 'http://localhost:8545');
        } catch(e) {
            console.error("Could not contact %s, due to: %O", this.getJsonRPCUrl(), e);
        }

        let WorkerDispatcher = web3.eth.contract(ContractStructure.WorkerDispatcher);
        this.contract = new WorkerDispatcher(ContractAddress);
        this.identity = web3.shh.newIdentity();
        this._worker = this.isWorker();
    }
    getCoinbase() {
        return web3.eth.coinbase;
    }

    formatBalance(wei) {
        let unit = 'wei';

        if (wei > 10e18) {
            unit = 'ether';
        } else if (wei > 10e15) {
            unit = 'finney';
        }

        return (unit !== 'wei' ? web3.fromWei(wei, unit).toFormat() : wei) + ' ' + unit;
    }

    // returns a work agreement if present for the given worker
    checkForAgreement(worker) {
        let agreementAddress = this.contract.workersInfo(worker)[3];
        if (web3.toDecimal(agreementAddress) != 0) {
            let WorkAgreement = web3.eth.contract(ContractStructure.WorkAgreement);
            return new WorkAgreement(agreementAddress);
        }
    }

    getDashboard() {
        let coinbase = this.getCoinbase();
        let peerCount = web3.net.peerCount;
        return Q.all([
                web3.eth.getBalancePromise(coinbase),
                web3.eth.getCodePromise(ContractAddress),
                web3.eth.getBlockPromise(web3.eth.blockNumber)
        ]).then(([balance, code, block]) => {
            let workers = this.contract.numWorkers();
            let timestamp = moment.unix(block.timestamp);
            if (code.length > 50) {
                code = code.substring(0, 60) + '…';
            }

            return [
                {label: "Coinbase", value: coinbase},
                {label: "Accounts", value: web3.eth.accounts},
                {label: "Balance", value: this.formatBalance(balance), title: balance},
                {label: "Latest block", value: block.number},
                {label: "Latest block hash", value: block.hash},
                {
                    label: "Latest block timestamp",
                    value: timestamp.fromNow(),
                    title: timestamp.format('llll')
                },
                {label: "Contract address", value: ContractAddress},
                {label: "Number of workers", value: workers.toString()},
                {label: "Number of peers", value: peerCount},
                {label: "Code", value: code}
            ];
        });
    }

    registerWorker(maxLength, price, name) {
        this.contract.registerWorker(maxLength, price, name);
        this._worker = true;
    }

    changeWorkerPrice(newPrice) {
        this.contract.changeWorkerPrice(newPrice);
    }

    buyContract(worker, redundancy, price, length) {
        let options = {
            value: length * price,
            gas: 500000
        };
        this.contract.sendTransaction(options)
            .buyContract(worker, redundancy, length);
    }

    isWorker() {
        let numWorkers = this.contract.numWorkers().toNumber();
        for (let i = 0; i < numWorkers; i++) {
            if (web3.eth.coinbase === this.contract.workerList(i)) {
                return true;
            }
        }
        return false;
    }

    findWorkers(length, price) {
        let numWorkers = this.contract.numWorkers().toNumber();
        let workers = [];
        for (let i = 0; i < numWorkers; i++) {
            let address = this.contract.workerList(i);
            let [wName, wLength, wPrice] = this.contract.workersInfo(address);
            wLength = wLength.toNumber()
            wPrice = wPrice.toNumber();

            if (length <= wLength && price >= wPrice) {
                workers.push({
                    pubkey: address,
                    name: wName,
                    length: wLength,
                    price: wPrice
                });
            }
        }

        return workers
    }

    subscribe(callback) {
        return PubSub.subscribe('chain', callback);
    }

    unsubscribe(token) {
        PubSub.unsubscribe(token);
    }

    getJsonRPCUrl() {
        return this._jsonRpcUrl;
    }

    setJsonRPCUrl(url) {
        if (!url.startsWith('http')) {
            url = 'http://' + url;
        }
        this._jsonRpcUrl = url;
        if (window.localStorage) {
            window.localStorage.setItem('rpc_url', this._jsonRpcUrl);
        }
        if (this.chainFilter) {
            // web3.reset();
            this.chainFilter.stopWatching();
        }
        web3.setProvider(new web3.providers.HttpProvider(this._jsonRpcUrl));
        this.chainFilter = web3.eth.filter('chain');

        PubSub.publish('chain');
        this.chainFilter.watch(() => {
            PubSub.publish('chain');
        });
    }

    sendMsg(to, data) {
        web3.shh.post({
            from: this.identity,
            to: to,
            payload: [ web3.fromAscii(data) ],
        });
    }

    askWorker(workerAddress, contractAddress) {
        web3.shh.post({
            from: this.identity,
            topic: workerAddress,
            payload: [ contractAddress ],
        });
    }
}

export default new EthClient();
<commit_msg>Now setting chainFilter to latest instead of chain<commit_after>import ContractAddress from "../fixtures/contractAddress.js";
import ContractStructure from "../fixtures/contractStructure.js";
import web3 from "web3";
import moment from "moment";
import Q from "q";
import PubSub from "pubsub-js"

web3.eth.getBalancePromise = Q.denodeify(web3.eth.getBalance);
web3.eth.getCodePromise = Q.denodeify(web3.eth.getCode);
web3.eth.getBlockPromise = Q.denodeify(web3.eth.getBlock);

class EthClient {
    constructor() {
        let url = null;
        if (window.localStorage && window.localStorage.getItem('rpc_url')) {
            url = window.localStorage.getItem('rpc_url');
        }
        try {
            this.setJsonRPCUrl(url || 'http://localhost:8545');
        } catch(e) {
            console.error("Could not contact %s, due to: %O", this.getJsonRPCUrl(), e);
        }

        let WorkerDispatcher = web3.eth.contract(ContractStructure.WorkerDispatcher);
        this.contract = new WorkerDispatcher(ContractAddress);
        this.identity = web3.shh.newIdentity();
        this._worker = this.isWorker();
    }
    getCoinbase() {
        return web3.eth.coinbase;
    }

    formatBalance(wei) {
        let unit = 'wei';

        if (wei > 10e18) {
            unit = 'ether';
        } else if (wei > 10e15) {
            unit = 'finney';
        }

        return (unit !== 'wei' ? web3.fromWei(wei, unit).toFormat() : wei) + ' ' + unit;
    }

    // returns a work agreement if present for the given worker
    checkForAgreement(worker) {
        let agreementAddress = this.contract.workersInfo(worker)[3];
        if (web3.toDecimal(agreementAddress) != 0) {
            let WorkAgreement = web3.eth.contract(ContractStructure.WorkAgreement);
            return new WorkAgreement(agreementAddress);
        }
    }

    getDashboard() {
        let coinbase = this.getCoinbase();
        let peerCount = web3.net.peerCount;
        return Q.all([
                web3.eth.getBalancePromise(coinbase),
                web3.eth.getCodePromise(ContractAddress),
                web3.eth.getBlockPromise(web3.eth.blockNumber)
        ]).then(([balance, code, block]) => {
            let workers = this.contract.numWorkers();
            let timestamp = moment.unix(block.timestamp);
            if (code.length > 50) {
                code = code.substring(0, 60) + '…';
            }

            return [
                {label: "Coinbase", value: coinbase},
                {label: "Accounts", value: web3.eth.accounts},
                {label: "Balance", value: this.formatBalance(balance), title: balance},
                {label: "Latest block", value: block.number},
                {label: "Latest block hash", value: block.hash},
                {
                    label: "Latest block timestamp",
                    value: timestamp.fromNow(),
                    title: timestamp.format('llll')
                },
                {label: "Contract address", value: ContractAddress},
                {label: "Number of workers", value: workers.toString()},
                {label: "Number of peers", value: peerCount},
                {label: "Code", value: code}
            ];
        });
    }

    registerWorker(maxLength, price, name) {
        this.contract.registerWorker(maxLength, price, name);
        this._worker = true;
    }

    changeWorkerPrice(newPrice) {
        this.contract.changeWorkerPrice(newPrice);
    }

    buyContract(worker, redundancy, price, length) {
        let options = {
            value: length * price,
            gas: 500000
        };
        this.contract.sendTransaction(options)
            .buyContract(worker, redundancy, length);
    }

    isWorker() {
        let numWorkers = this.contract.numWorkers().toNumber();
        for (let i = 0; i < numWorkers; i++) {
            if (web3.eth.coinbase === this.contract.workerList(i)) {
                return true;
            }
        }
        return false;
    }

    findWorkers(length, price) {
        let numWorkers = this.contract.numWorkers().toNumber();
        let workers = [];
        for (let i = 0; i < numWorkers; i++) {
            let address = this.contract.workerList(i);
            let [wName, wLength, wPrice] = this.contract.workersInfo(address);
            wLength = wLength.toNumber()
            wPrice = wPrice.toNumber();

            if (length <= wLength && price >= wPrice) {
                workers.push({
                    pubkey: address,
                    name: wName,
                    length: wLength,
                    price: wPrice
                });
            }
        }

        return workers
    }

    subscribe(callback) {
        return PubSub.subscribe('chain', callback);
    }

    unsubscribe(token) {
        PubSub.unsubscribe(token);
    }

    getJsonRPCUrl() {
        return this._jsonRpcUrl;
    }

    setJsonRPCUrl(url) {
        if (!url.startsWith('http')) {
            url = 'http://' + url;
        }
        this._jsonRpcUrl = url;
        if (window.localStorage) {
            window.localStorage.setItem('rpc_url', this._jsonRpcUrl);
        }
        if (this.chainFilter) {
            // web3.reset();
            this.chainFilter.stopWatching();
        }
        web3.setProvider(new web3.providers.HttpProvider(this._jsonRpcUrl));
        this.chainFilter = web3.eth.filter('latest');

        PubSub.publish('chain');
        this.chainFilter.watch(() => {
            PubSub.publish('chain');
        });
    }

    sendMsg(to, data) {
        web3.shh.post({
            from: this.identity,
            to: to,
            payload: [ web3.fromAscii(data) ],
        });
    }

    askWorker(workerAddress, contractAddress) {
        web3.shh.post({
            from: this.identity,
            topic: workerAddress,
            payload: [ contractAddress ],
        });
    }
}

export default new EthClient();
<|endoftext|>


<commit_before>var YUITest = require('yuitest'),
    Assert = YUITest.Assert,
    ArrayAssert = YUITest.ArrayAssert,
    path = require('path'),
    fs = require('fs'),
    Y = require(path.join(__dirname, '../', 'lib', 'index'));

//Move to the test dir before running the tests.
process.chdir(__dirname);

var suite = new YUITest.TestSuite('Options Test Suite');

suite.add(new YUITest.TestCase({
    name: "Server Options",
    'test: server': function() {
        var options = Y.Options([
            '--server'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(3000, options.port, 'Failed to set default port');
    },
    'test: server with port': function() {
        var options = Y.Options([
            '--server',
            '5000'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(5000, options.port, 'Failed to set port');
    },
    'test: server with default port and following argument': function() {
        var options = Y.Options([
            '--server',
            './foo'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(3000, options.port, 'Failed to set default port');
        Assert.isArray(options.paths, 'Failed to set path');
        Assert.areSame('./foo', options.paths[0], 'Failed to set path after empty --server');
    }
}));

suite.add(new YUITest.TestCase({
    name: "Various Options",
    "test: long quiet option": function() {
        var options = Y.Options([
            '--quiet'
        ]);

        Assert.isTrue(options.quiet, 'Failed to set long quiet');
    },
    "test: short quiet option": function() {
        var options = Y.Options([
            '-q'
        ]);

        Assert.isTrue(options.quiet, 'Failed to set short quiet');
    },
    "test: short config": function() {
        var options = Y.Options([
            '-c',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: --config': function() {
        var options = Y.Options([
            '--config',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: --configfile': function() {
        var options = Y.Options([
            '--configfile',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: -e': function() {
        var options = Y.Options([
            '-e',
            '.foo'
        ]);

        Assert.areSame('.foo', options.extension, 'Failed to set extension');
    },
    'test: --extension': function() {
        var options = Y.Options([
            '--extension',
            '.foo'
        ]);

        Assert.areSame('.foo', options.extension, 'Failed to set extension');
    },
    'test: -x': function() {
        var options = Y.Options([
            '-x',
            'foo,bar,baz'
        ]);

        Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
    },
    'test: --exclude': function() {
        var options = Y.Options([
            '--exclude',
            'foo,bar,baz'
        ]);

        Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
    },
    'test: --project-version': function() {
        var options = Y.Options([
            '--project-version',
            '6.6.6'
        ]);

        Assert.areSame('6.6.6', options.version, 'Failed to set version');
    },
    'test: --no-color': function() {
        var options = Y.Options([
            '--no-color',
        ]);

        Assert.isTrue(options.nocolor, 'Failed to set nocolor');
        Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
    },
    'test: -N': function() {
        var options = Y.Options([
            '-N',
        ]);

        Assert.isTrue(options.nocolor, 'Failed to set nocolor');
        Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
    },
    'test: --no-code': function() {
        var options = Y.Options([
            '--no-code',
        ]);

        Assert.isTrue(options.nocode, 'Failed to set nocode');
    },
    'test: -C': function() {
        var options = Y.Options([
            '-C',
        ]);

        Assert.isTrue(options.nocode, 'Failed to set nocode');
    },
    'test: --norecurse': function() {
        var options = Y.Options([
            '--norecurse',
        ]);

        Assert.isTrue(options.norecurse, 'Failed to set norecurse');
    },
    'test: -n': function() {
        var options = Y.Options([
            '-n',
        ]);

        Assert.isTrue(options.norecurse, 'Failed to set norecurse');
    },
    'test: --selleck': function() {
        var options = Y.Options([
            '--selleck',
        ]);

        Assert.isTrue(options.selleck, 'Failed to set selleck');
    },
    'test: -S': function() {
        var options = Y.Options([
            '-S',
        ]);

        Assert.isTrue(options.selleck, 'Failed to set selleck');
    }
}));

YUITest.TestRunner.add(suite);

<commit_msg>Tests for #51<commit_after>var YUITest = require('yuitest'),
    Assert = YUITest.Assert,
    ArrayAssert = YUITest.ArrayAssert,
    path = require('path'),
    fs = require('fs'),
    Y = require(path.join(__dirname, '../', 'lib', 'index'));

//Move to the test dir before running the tests.
process.chdir(__dirname);

var suite = new YUITest.TestSuite('Options Test Suite');

suite.add(new YUITest.TestCase({
    name: "Server Options",
    'test: server': function() {
        var options = Y.Options([
            '--server'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(3000, options.port, 'Failed to set default port');
    },
    'test: server with port': function() {
        var options = Y.Options([
            '--server',
            '5000'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(5000, options.port, 'Failed to set port');
    },
    'test: server with default port and following argument': function() {
        var options = Y.Options([
            '--server',
            './foo'
        ]);

        Assert.isTrue(options.server, 'Failed to set server option');
        Assert.areSame(3000, options.port, 'Failed to set default port');
        Assert.isArray(options.paths, 'Failed to set path');
        Assert.areSame('./foo', options.paths[0], 'Failed to set path after empty --server');
    }
}));

suite.add(new YUITest.TestCase({
    name: "Various Options",
    "test: long quiet option": function() {
        var options = Y.Options([
            '--quiet'
        ]);

        Assert.isTrue(options.quiet, 'Failed to set long quiet');
    },
    "test: short quiet option": function() {
        var options = Y.Options([
            '-q'
        ]);

        Assert.isTrue(options.quiet, 'Failed to set short quiet');
    },
    "test: short config": function() {
        var options = Y.Options([
            '-c',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: --config': function() {
        var options = Y.Options([
            '--config',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: --configfile': function() {
        var options = Y.Options([
            '--configfile',
            './foo.json'
        ]);

        Assert.areSame('./foo.json', options.configfile, 'Failed to set config');
    },
    'test: -e': function() {
        var options = Y.Options([
            '-e',
            '.foo'
        ]);

        Assert.areSame('.foo', options.extension, 'Failed to set extension');
    },
    'test: --extension': function() {
        var options = Y.Options([
            '--extension',
            '.foo'
        ]);

        Assert.areSame('.foo', options.extension, 'Failed to set extension');
    },
    'test: -x': function() {
        var options = Y.Options([
            '-x',
            'foo,bar,baz'
        ]);

        Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
    },
    'test: --exclude': function() {
        var options = Y.Options([
            '--exclude',
            'foo,bar,baz'
        ]);

        Assert.areSame('foo,bar,baz', options.exclude, 'Failed to set exclude');
    },
    'test: --project-version': function() {
        var options = Y.Options([
            '--project-version',
            '6.6.6'
        ]);

        Assert.areSame('6.6.6', options.version, 'Failed to set version');
    },
    'test: --no-color': function() {
        var options = Y.Options([
            '--no-color',
        ]);

        Assert.isTrue(options.nocolor, 'Failed to set nocolor');
        Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
    },
    'test: -N': function() {
        var options = Y.Options([
            '-N',
        ]);

        Assert.isTrue(options.nocolor, 'Failed to set nocolor');
        Assert.isFalse(Y.config.useColor, 'Failed to set Y.config.useColor');
    },
    'test: --no-code': function() {
        var options = Y.Options([
            '--no-code',
        ]);

        Assert.isTrue(options.nocode, 'Failed to set nocode');
    },
    'test: -C': function() {
        var options = Y.Options([
            '-C',
        ]);

        Assert.isTrue(options.nocode, 'Failed to set nocode');
    },
    'test: --norecurse': function() {
        var options = Y.Options([
            '--norecurse',
        ]);

        Assert.isTrue(options.norecurse, 'Failed to set norecurse');
    },
    'test: -n': function() {
        var options = Y.Options([
            '-n',
        ]);

        Assert.isTrue(options.norecurse, 'Failed to set norecurse');
    },
    'test: --selleck': function() {
        var options = Y.Options([
            '--selleck',
        ]);

        Assert.isTrue(options.selleck, 'Failed to set selleck');
    },
    'test: -S': function() {
        var options = Y.Options([
            '-S',
        ]);

        Assert.isTrue(options.selleck, 'Failed to set selleck');
    },
    'test: -T simple': function() {
        var options = Y.Options([
            '-T',
            'simple'
        ]);
        var p = path.join(__dirname, '../themes/simple');
        Assert.areEqual(p, options.themedir);
    },
    'test: --theme simple': function() {
        var options = Y.Options([
            '--theme',
            'simple'
        ]);
        var p = path.join(__dirname, '../themes/simple');
        Assert.areEqual(p, options.themedir);
    },
    'test: --theme foobar': function() {
        var options = Y.Options([
            '--theme',
            'foobar'
        ]);
        var p = path.join(__dirname, '../themes/foobar');
        Assert.areEqual(p, options.themedir);
    },
    'test: --themedir ./foobar': function() {
        var options = Y.Options([
            '--themedir',
            './foobar'
        ]);
        Assert.areEqual('./foobar', options.themedir);
    }
}));

YUITest.TestRunner.add(suite);

<|endoftext|>


<commit_before>/**
 * Created by brad on 4/8/17.
 */

/**
 * Copyright Bradley Smith - bradley.1.smith@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function (RED) {
  "use strict";
  // NPM Imports
  const i2c = require('i2c-bus');
  let BigNumber = require('bignumber.js');
  BigNumber.config({DECIMAL_PLACES: 4});

  // Local Imports
  // const Measurement = require('./Measurement.js');

  const HTU21DFAddress = 0x40;

  const commandMeasureTemperatureHoldMaster = 0xE3;
  const commandMeasureHumidityHoldMaster = 0xE5;
  const commandMeasureTemperatureNoHoldMaster = 0xF3;
  const commandMeasureHumidityNoHoldMaster = 0xF5;
  const commandWriteUserRegister = 0xE6;
  const commandReadUserRegister = 0xE7;
  const commandSoftReset = 0xFE;

  const waitTimeTemperature14BIT = 50;//ms (factory default)
  const waitTimeTemperature13BIT = 25;//ms
  const waitTimeTemperature12BIT = 13;//ms
  const waitTimeTemperature11BIT = 7;//ms

  const waitTimeRH12BIT = 16;//ms (factory default)
  const waitTimeRH11BIT = 8;//ms
  const waitTimeRH10BIT = 5;//ms
  const waitTimeRH8BIT = 3;//ms

  const A = new BigNumber('8.1332');
  const B = new BigNumber('1763.39');
  const C = new BigNumber('235.66');

  const dateFormatOptions = {
    year: 'numeric', month: 'numeric', day: 'numeric',
    hour: 'numeric', minute: 'numeric', second: 'numeric',
    hour12: false, timeZone: 'America/New_York'
  };

  let i2cBus = undefined;

  function computeDewpoint(temp, rh, node) {
    let exponent = A.minus(B.div(C.plus(temp))).toNumber();
    node.log(`exponent -> ${exponent}`);
    let pp = Math.pow(10, exponent);
    node.log(`pp -> ${pp}`);
    let log10Operand = pp * rh / 100.0;
    node.log(`log10Operand -> ${log10Operand}`);
    let TDP = -1 * ( C.toNumber() + (B.toNumber() / (Math.log10(log10Operand) - A.toNumber())));
    node.log(`Dew Point Temperature -> ${TDP}`);
    let TDPStr = TDP.toString();
    if (TDPStr.length > 10) {
      TDP = Number( TDPStr.substr(0, 9));
      node.log(`(chopped) Dew Point Temperature -> ${TDP}`);
    }
    return TDP;
  }

  // The main node definition - most things happen in here
  function htu21df(config) {

    // Create a RED node
    RED.nodes.createNode(this, config);

    // copy "this" object in case we need it in context of callbacks of other functions.
    let node = this;

    node.log(JSON.stringify(config));
    if (i2cBus == undefined) {
      i2cBus = i2c.openSync(1);
      node.log("opened i2cBus -> " + i2cBus);
    }
    node.log("starting up htu21df");

    node.address = HTU21DFAddress;
    node.temperature = -9999;
    node.relativeHumidity = -9999;
    node.dewPoint = -9999;

    // Store local copies of the node configuration (as defined in the .html)
    // this.topic = config.topic;

    // respond to inputs....
    this.on('input', (msg) => {

      let command = msg.payload; // One of:  measure, set_config, get_config, ... TODO - add other input types support
      if (command) {
        if ("measure" == command) {
          // TODO - dynamically set desired resolution before measuring...

          // TODO - for now, just measure at device defaults
          let tempBuffer = new Uint8Array(2);
          let humidityBuffer = new Uint8Array(2);

          let now = Date.now();

          measure(node).then((resolve) => {
            let result = {
              device:"sensor",
              name: "htu21df",
              temperatureC: node.temperature,
              temperatureCString: node.temperature + " \u2103",
              temperatureF: node.temperature.toNumber()*1.8 + 32,
              relativeHumidity: node.relativeHumidity,
              relativeHumidityString: node.relativeHumidity + " %",
              dewPointC: node.dewPoint,
              dewPointCString: node.dewPoint + " \u2103",
              timestamp: new Date()
            };

            let thingShadow = {
              state: {
                "reported": {
                  "device": "sensor",
                  "name": "htu21df",
                  "temperature": node.temperature.times(1.8).add(32.0).toNumber(),
                  "temperatureUnits": "degrees Fahrenheit",
                  "relativeHumidity": node.relativeHumidity.toNumber(),
                  "dewPoint": new BigNumber(node.dewPoint).times(1.8).add(32.0).toNumber(),
                  "timestamp": node.measurementDate
                }
              }
            };

            node.send([
              {topic: 'htu21df', payload: result},
              {topic: 'htu21df', payload: thingShadow}
            ]);

          }, (reject) => {
            msg.payload = `${reject}`;
            node.send(msg);
          });

        }
      }
    });

    this.on("close", () => {
      node.log("close");
      // Called when the node is shutdown - eg on redeploy.
      // Allows ports to be closed, connections dropped etc.
      // eg: node.client.disconnect();
    });
  }

  // Register the node by name. This must be called before overriding any of the
  // Node functions.
  RED.nodes.registerType("htu21df", htu21df);

  function measure(node) {
    return new Promise( ( resolve, reject ) => {
      let tempBuffer = new Uint8Array(2);
      let humidityBuffer = new Uint8Array(2);

      i2cBus.sendByte(node.address, commandMeasureTemperatureNoHoldMaster, (err) => {
        if (err) {
          let errMsg = `send read temperature command error:  ${err}`;
          node.error(errMsg);
          reject( errMsg );
        } else {
          setTimeout( () => {
            i2cBus.i2cRead(node.address, tempBuffer.length, tempBuffer, (err, bytesRead, buffer) => {
              if (err) {
                let errMsg = `read temperature value error:  ${err}`;
                node.error(errMsg);
                reject(errMsg);
              } else {
                let dataView = new DataView(buffer.buffer);
                node.temperature = new BigNumber(dataView.getUint16(0), 10).div(65536).times('175.72').minus('46.85');
                // this.temperature = -46.85 + 175.72 * (dataView.getUint16(0) / 65536);
                node.log(`Temperature:  ${node.temperature} \u2103`);
                // measure relative humidity
                i2cBus.sendByte(node.address, commandMeasureHumidityNoHoldMaster, (err) => {
                  if (err) {
                    let errMsg = `send measure humidity command error:  ${err}`;
                    node.error(errMsg);
                    reject( errMsg );
                  } else {
                    setTimeout( () => {
                      i2cBus.i2cRead(node.address, humidityBuffer.length, humidityBuffer, (err, bytesRead, buffer) => {
                        if (err) {
                          let errMsg = `read humidity value error:  ${err}`;
                          node.error(errMsg );
                          reject( errMsg );
                        } else {
                          node.measurementDate = new Date().toLocaleString('en-US', dateFormatOptions);
                          let dataView = new DataView(buffer.buffer);
                          node.relativeHumidity = new BigNumber(dataView.getUint16(0)).div(65536).times(125).minus(6);
                          // this.relativeHumidity = -6.0 + 125 * (dataView.getUint16(0) / 65536);
                          node.log(`HTU21DF RH:  ${node.relativeHumidity} %`);
                          node.dewPoint = computeDewpoint(node.temperature, node.relativeHumidity, node);
                          // node.log("HTU21DF Dew point:  " + DP + ' \u2103');
                          resolve( [node.temperature, node.relativeHumidity, node.dewPoint] );
                        }
                      });
                    }, waitTimeRH12BIT);
                  }
                });
              }
            });
          }, waitTimeTemperature14BIT /* ms */);
        }
      });
    });
  }

}<commit_msg>white space<commit_after>/**
 * Created by brad on 4/8/17.
 */

/**
 * Copyright Bradley Smith - bradley.1.smith@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function (RED) {
  "use strict";
  // NPM Imports
  const i2c = require('i2c-bus');
  let BigNumber = require('bignumber.js');
  BigNumber.config({DECIMAL_PLACES: 4});

  // Local Imports
  // const Measurement = require('./Measurement.js');

  const HTU21DFAddress = 0x40;

  const commandMeasureTemperatureHoldMaster = 0xE3;
  const commandMeasureHumidityHoldMaster = 0xE5;
  const commandMeasureTemperatureNoHoldMaster = 0xF3;
  const commandMeasureHumidityNoHoldMaster = 0xF5;
  const commandWriteUserRegister = 0xE6;
  const commandReadUserRegister = 0xE7;
  const commandSoftReset = 0xFE;

  const waitTimeTemperature14BIT = 50;//ms (factory default)
  const waitTimeTemperature13BIT = 25;//ms
  const waitTimeTemperature12BIT = 13;//ms
  const waitTimeTemperature11BIT = 7;//ms

  const waitTimeRH12BIT = 16;//ms (factory default)
  const waitTimeRH11BIT = 8;//ms
  const waitTimeRH10BIT = 5;//ms
  const waitTimeRH8BIT = 3;//ms

  const A = new BigNumber('8.1332');
  const B = new BigNumber('1763.39');
  const C = new BigNumber('235.66');

  const dateFormatOptions = {
    year: 'numeric', month: 'numeric', day: 'numeric',
    hour: 'numeric', minute: 'numeric', second: 'numeric',
    hour12: false, timeZone: 'America/New_York'
  };

  let i2cBus = undefined;

  function computeDewpoint(temp, rh, node) {
    let exponent = A.minus(B.div(C.plus(temp))).toNumber();
    node.log(`exponent -> ${exponent}`);
    let pp = Math.pow(10, exponent);
    node.log(`pp -> ${pp}`);
    let log10Operand = pp * rh / 100.0;
    node.log(`log10Operand -> ${log10Operand}`);
    let TDP = -1 * ( C.toNumber() + (B.toNumber() / (Math.log10(log10Operand) - A.toNumber())));
    node.log(`Dew Point Temperature -> ${TDP}`);
    let TDPStr = TDP.toString();
    if (TDPStr.length > 10) {
      TDP = Number( TDPStr.substr(0, 9));
      node.log(`(chopped) Dew Point Temperature -> ${TDP}`);
    }
    return TDP;
  }

  // The main node definition - most things happen in here
  function htu21df(config) {

    // Create a RED node
    RED.nodes.createNode(this, config);

    // copy "this" object in case we need it in context of callbacks of other functions.
    let node = this;

    node.log(JSON.stringify(config));
    if (i2cBus == undefined) {
      i2cBus = i2c.openSync(1);
      node.log("opened i2cBus -> " + i2cBus);
    }
    node.log("starting up htu21df");

    node.address = HTU21DFAddress;
    node.temperature = -9999;
    node.relativeHumidity = -9999;
    node.dewPoint = -9999;

    // Store local copies of the node configuration (as defined in the .html)
    // this.topic = config.topic;

    // respond to inputs....
    this.on('input', (msg) => {

      let command = msg.payload; // One of:  measure, set_config, get_config, ... TODO - add other input types support
      if (command) {
        if ("measure" == command) {
          // TODO - dynamically set desired resolution before measuring...

          // TODO - for now, just measure at device defaults
          let tempBuffer = new Uint8Array(2);
          let humidityBuffer = new Uint8Array(2);

          let now = Date.now();

          measure(node).then((resolve) => {
            let result = {
              device:"sensor",
              name: "htu21df",
              temperatureC: node.temperature,
              temperatureCString: node.temperature + " \u2103",
              temperatureF: node.temperature.toNumber()*1.8 + 32,
              relativeHumidity: node.relativeHumidity,
              relativeHumidityString: node.relativeHumidity + " %",
              dewPointC: node.dewPoint,
              dewPointCString: node.dewPoint + " \u2103",
              timestamp: new Date()
            };

            let thingShadow = {
              state: {
                "reported": {
                  "device": "sensor",
                  "name": "htu21df",
                  "temperature": node.temperature.times(1.8).add(32.0).toNumber(),
                  "temperatureUnits": "degrees Fahrenheit",
                  "relativeHumidity": node.relativeHumidity.toNumber(),
                  "dewPoint": new BigNumber(node.dewPoint).times(1.8).add(32.0).toNumber(),
                  "timestamp": node.measurementDate
                }
              }
            };

            node.send([
              {topic: 'htu21df', payload: result},
              {topic: 'htu21df', payload: thingShadow}
            ]);

          }, (reject) => {
            msg.payload = `${reject}`;
            node.send(msg);
          });

        }
      }
    });

    this.on("close", () => {
      node.log("close");
      // Called when the node is shutdown - eg on redeploy.
      // Allows ports to be closed, connections dropped etc.
      // eg: node.client.disconnect();
    });
  }

  // Register the node by name. This must be called before overriding any of the
  // Node functions.
  RED.nodes.registerType("htu21df", htu21df);

  function measure(node) {
    return new Promise( ( resolve, reject ) => {
      let tempBuffer = new Uint8Array(2);
      let humidityBuffer = new Uint8Array(2);

      i2cBus.sendByte(node.address, commandMeasureTemperatureNoHoldMaster, (err) => {
        if (err) {
          let errMsg = `send read temperature command error:  ${err}`;
          node.error(errMsg);
          reject( errMsg );
        } else {
          setTimeout( () => {
            i2cBus.i2cRead(node.address, tempBuffer.length, tempBuffer, (err, bytesRead, buffer) => {
              if (err) {
                let errMsg = `read temperature value error:  ${err}`;
                node.error(errMsg);
                reject(errMsg);
              } else {
                let dataView = new DataView(buffer.buffer);
                node.temperature = new BigNumber(dataView.getUint16(0), 10).div(65536).times('175.72').minus('46.85');
                // this.temperature = -46.85 + 175.72 * (dataView.getUint16(0) / 65536);
                node.log(`Temperature:  ${node.temperature} \u2103`);
                // measure relative humidity
                i2cBus.sendByte(node.address, commandMeasureHumidityNoHoldMaster, (err) => {
                  if (err) {
                    let errMsg = `send measure humidity command error:  ${err}`;
                    node.error(errMsg);
                    reject( errMsg );
                  } else {
                    setTimeout( () => {
                      i2cBus.i2cRead(node.address, humidityBuffer.length, humidityBuffer, (err, bytesRead, buffer) => {
                        if (err) {
                          let errMsg = `read humidity value error:  ${err}`;
                          node.error(errMsg );
                          reject( errMsg );
                        } else {
                          node.measurementDate = new Date().toLocaleString('en-US', dateFormatOptions);
                          let dataView = new DataView(buffer.buffer);
                          node.relativeHumidity = new BigNumber(dataView.getUint16(0)).div(65536).times(125).minus(6);
                          // this.relativeHumidity = -6.0 + 125 * (dataView.getUint16(0) / 65536);
                          node.log(`HTU21DF RH:  ${node.relativeHumidity} %`);
                          node.dewPoint = computeDewpoint(node.temperature, node.relativeHumidity, node);
                          // node.log("HTU21DF Dew point:  " + DP + ' \u2103');
                          resolve( [node.temperature, node.relativeHumidity, node.dewPoint] );
                        }
                      });
                    }, waitTimeRH12BIT);
                  }
                });
              }
            });
          }, waitTimeTemperature14BIT /* ms */);
        }
      });
    });
  }

}<|endoftext|>


<commit_before>"use strict";

/*
firstMove function returns the position (assuming the tic-tac-toe board is numbered 0-8) a player should take for their first move.
If an empty board is passed in, the function assumes it is making the first move in the game.
*/

function firstMove(position){

	return position.indexOf('X') === 4 || position.indexOf('X') === -1 ? 0 : 4

}

module.exports = firstMove;<commit_msg>refactored wording for firstMove function<commit_after>"use strict";

/*
firstMove function returns the position (assuming the tic-tac-toe board is numbered 0-8) a player should take for their first move.
If an empty board is passed in, the function assumes it is making the first move in the game.
*/

function firstMove(board){

	return board.indexOf('X') === 4 || board.indexOf('X') === -1 ? 0 : 4

}

module.exports = firstMove;<|endoftext|>


<commit_before>'use strict';
// Call spamassassin via spamd
/* jshint node: true */
/* global DENY */

var sock = require('./line_socket');
var utils = require('./utils');

exports.register = function () {
    var plugin = this;
    plugin.load_spamassassin_ini();
};

exports.load_spamassassin_ini = function () {
    var plugin = this;
    plugin.loginfo("loading spamassassin.ini");
    plugin.cfg = plugin.config.get('spamassassin.ini', plugin.load_spamassassin_ini);

    var defaults = {
        spamd_socket: 'localhost:783',
        max_size:     500000,
        old_headers_action: "rename",
        subject_prefix: "*** SPAM ***",
    };

    for (var key in defaults) {
        if (plugin.cfg.main[key]) continue;
        plugin.cfg.main[key] = defaults[key];
    }

    ['reject_threshold', 'relay_reject_threshold',
    'munge_subject_threshold', 'max_size'].forEach(function (item) {
        if (!plugin.cfg.main[item]) return;
        plugin.cfg.main[item] = Number(plugin.cfg.main[item]);
    });
};

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    if (plugin.msg_too_big(connection)) return next();

    var username        = plugin.get_spamd_username(connection);
    var headers         = plugin.get_spamd_headers(connection, username);
    var socket          = plugin.get_spamd_socket(next, connection, headers);

    var spamd_response = { headers: {} };
    var state = 'line0';
    var last_header;

    socket.on('line', function (line) {
        connection.logprotocol(plugin, "Spamd C: " + line + ' state=' + state);
        line = line.replace(/\r?\n/, '');
        if (state === 'line0') {
            spamd_response.line0 = line;
            state = 'response';
        }
        else if (state === 'response') {
            if (line.match(/\S/)) {
                var matches = line.match(/Spam: (True|False) ; (-?\d+\.\d) \/ (-?\d+\.\d)/);
                if (matches) {
                    spamd_response.flag = matches[1];
                    spamd_response.score = matches[2];
                    spamd_response.hits = matches[2];  // backwards compat
                    spamd_response.reqd = matches[3];
                    spamd_response.flag = spamd_response.flag === 'True' ? 'Yes' : 'No';
                }
            }
            else {
                state = 'headers';
            }
        }
        else if (state === 'headers') {
            var m = line.match(/^X-Spam-([\x21-\x39\x3B-\x7E]+):\s*(.*)/);
            if (m) {
                connection.logdebug(plugin, "header: " + line);
                last_header = m[1];
                spamd_response.headers[m[1]] = m[2];
                return;
            }
            var fold;
            if (last_header && (fold = line.match(/^(\s+.*)/))) {
                spamd_response.headers[last_header] += "\r\n" + fold[1];
                return;
            }
            last_header = '';
        }
    });

    socket.on('end', function () {
        // Abort if the transaction is gone
        if (!connection.transaction) return next();

        if (spamd_response.headers && spamd_response.headers.Tests) {
            spamd_response.tests = spamd_response.headers.Tests;
        }
        if (spamd_response.tests === undefined) {
            // strip the 'tests' from the X-Spam-Status header
            if (spamd_response.headers && spamd_response.headers.Status) {
                // SpamAssassin appears to have a bug that causes a space not to
                // be added before autolearn= when the header line has been folded.
                // So we modify the regexp here not to match autolearn onwards.
                var tests = /tests=((?:(?!autolearn)[^ ])+)/.exec(spamd_response.headers.Status.replace(/\r?\n\t/g,''));
                if (tests) { spamd_response.tests = tests[1]; }
            }
        }

        // do stuff with the results...
        connection.transaction.notes.spamassassin = spamd_response;

        plugin.fixup_old_headers(connection.transaction);
        plugin.do_header_updates(connection, spamd_response);
        plugin.log_results(connection, spamd_response);

        var exceeds_err = plugin.score_too_high(connection, spamd_response);
        if (exceeds_err) return next(DENY, exceeds_err);

        plugin.munge_subject(connection, spamd_response.score);

        return next();
    });
};

exports.fixup_old_headers = function (transaction) {
    var plugin = this;
    var action = plugin.cfg.main.old_headers_action;
    var headers = transaction.notes.spamassassin.headers;

    var key;
    switch (action) {
        case "keep":
            break;
        case "drop":
            for (key in headers) {
                if (!key) continue;
                transaction.remove_header('X-Spam-' + key);
            }
            break;
        // case 'rename':
        default:
            for (key in headers) {
                if (!key) continue;
                key = 'X-Spam-' + key;
                var old_val = transaction.header.get(key);
                transaction.remove_header(key);
                if (old_val) {
                    // plugin.logdebug(plugin, "header: " + key + ', ' + old_val);
                    transaction.add_header(key.replace(/^X-/, 'X-Old-'), old_val);
                }
            }
            break;
    }
};

exports.munge_subject = function (connection, score) {
    var plugin = this;
    var munge = plugin.cfg.main.munge_subject_threshold;
    if (!munge) return;
    if (parseFloat(score) < parseFloat(munge)) return;

    var subj = connection.transaction.header.get('Subject');
    var subject_re = new RegExp('^' + utils.regexp_escape(plugin.cfg.main.subject_prefix));
    if (subject_re.test(subj)) return;    // prevent double munge

    connection.transaction.remove_header('Subject');
    connection.transaction.add_header('Subject', plugin.cfg.main.subject_prefix + " " + subj);
};

exports.do_header_updates = function (connection, spamd_response) {
    var plugin = this;
    if (spamd_response.flag === 'Yes') {
        // X-Spam-Flag is added by SpamAssassin
        connection.transaction.remove_header('precedence');
        connection.transaction.add_header('Precedence', 'junk');
    }

    var modern = plugin.cfg.main.modern_status_syntax;
    for (var key in spamd_response.headers) {
        if (!key || key === '' || key === undefined) continue;
        var val = spamd_response.headers[key];
        if (val === undefined) { val = ''; }

        if (key === 'Status' && !modern) {
            var legacy = spamd_response.headers[key].replace(/ score=/,' hits=');
            connection.transaction.add_header('X-Spam-Status', legacy);
            continue;
        }
        connection.transaction.add_header('X-Spam-' + key, val);
    }
};

exports.score_too_high = function (connection, spamd_response) {
    var plugin = this;
    var score = spamd_response.score;
    if (connection.relaying) {
        var rmax = plugin.cfg.main.relay_reject_threshold;
        if (rmax && (score >= rmax)) {
            return "spam score exceeded relay threshold";
        }
    }

    var max = plugin.cfg.main.reject_threshold;
    if (max && (score >= max)) {
        return "spam score exceeded threshold";
    }

    return false;
};

exports.get_spamd_username = function(connection) {
    var plugin = this;

    var user = connection.transaction.notes.spamd_user;  // 1st priority
    if (user && user !== undefined) return user;

    if (!plugin.cfg.main.spamd_user) return 'default';   // when not defined
    user = plugin.cfg.main.spamd_user;

    // Enable per-user SA prefs
    if (user === 'first-recipient') {                // special cases
        return connection.transaction.rcpt_to[0].address();
    }
    if (user === 'all-recipients') {
        throw "Unimplemented";
        // TODO: pass the message through SA for each recipient. Then apply
        // the least strict result to the connection. That is useful when
        // one user blacklists a sender that another user wants to get mail
        // from. If this is something you care about, this is the spot.
    }
    return user;
};

exports.get_spamd_headers = function(connection, username) {
    // http://svn.apache.org/repos/asf/spamassassin/trunk/spamd/PROTOCOL
    var headers = [
        'HEADERS SPAMC/1.3',
        'User: ' + username,
        '',
        'X-Envelope-From: ' + connection.transaction.mail_from.address(),
        'X-Haraka-UUID: ' + connection.transaction.uuid,
    ];
    if (connection.relaying) {
        headers.push('X-Haraka-Relay: true');
    }
    return headers;
};

exports.get_spamd_socket = function(next, connection, headers) {
    var plugin = this;
    // TODO: support multiple spamd backends

    var socket = new sock.Socket();
    socket.is_connected = false;
    var results_timeout = parseInt(plugin.cfg.main.results_timeout) || 300;

    socket.on('connect', function () {
        if (!connection.transaction) {
            socket.end();
            return next();
        }
        this.is_connected = true;
        // Reset timeout
        this.setTimeout(results_timeout * 1000);
        socket.write(headers.join("\r\n") + "\r\n");
        connection.transaction.message_stream.pipe(socket);
    });

    socket.on('error', function (err) {
        connection.logerror(plugin, 'connection failed: ' + err);
        // TODO: optionally DENYSOFT
        // TODO: add a transaction note
        return next();
    });

    socket.on('timeout', function () {
        if (!this.is_connected) {
            connection.logerror(plugin, 'connection timed out');
        }
        else {
            connection.logerror(plugin, 'timeout waiting for results');
        }
        socket.end();
        return next();
    });

    var connect_timeout = parseInt(plugin.cfg.main.connect_timeout) || 30;
    socket.setTimeout(connect_timeout * 1000);

    if (plugin.cfg.main.spamd_socket.match(/\//)) {    // assume unix socket
        socket.connect(plugin.cfg.main.spamd_socket);
    }
    else {
        var hostport = plugin.cfg.main.spamd_socket.split(/:/);
        socket.connect((hostport[1] || 783), hostport[0]);
    }

    return socket;
};

exports.msg_too_big = function(connection) {
    var plugin = this;
    if (!plugin.cfg.main.max_size) return false;

    var size = connection.transaction.data_bytes;

    var max = plugin.cfg.main.max_size;
    if (size <= max) { return false; }
    connection.loginfo(plugin, 'skipping, size ' + utils.prettySize(size) + ' exceeds max: ' + utils.prettySize(max));
    return true;
};

exports.log_results = function(connection, spamd_response) {
    var plugin = this;
    var cfg = plugin.cfg.main;
    connection.loginfo(plugin, "status=" + spamd_response.flag +
          ', score=' + spamd_response.score +
          ', required=' + spamd_response.reqd +
          ', reject=' + ((connection.relaying) ?
             (cfg.relay_reject_threshold || cfg.reject_threshold) : cfg.reject_threshold) +
          ', tests="' + spamd_response.tests + '"');
};
<commit_msg>spamd: more informative spamd connect failure log<commit_after>'use strict';
// Call spamassassin via spamd
/* jshint node: true */
/* global DENY */

var sock = require('./line_socket');
var utils = require('./utils');

exports.register = function () {
    var plugin = this;
    plugin.load_spamassassin_ini();
};

exports.load_spamassassin_ini = function () {
    var plugin = this;
    plugin.loginfo("loading spamassassin.ini");
    plugin.cfg = plugin.config.get('spamassassin.ini', plugin.load_spamassassin_ini);

    var defaults = {
        spamd_socket: 'localhost:783',
        max_size:     500000,
        old_headers_action: "rename",
        subject_prefix: "*** SPAM ***",
    };

    for (var key in defaults) {
        if (plugin.cfg.main[key]) continue;
        plugin.cfg.main[key] = defaults[key];
    }

    ['reject_threshold', 'relay_reject_threshold',
    'munge_subject_threshold', 'max_size'].forEach(function (item) {
        if (!plugin.cfg.main[item]) return;
        plugin.cfg.main[item] = Number(plugin.cfg.main[item]);
    });
};

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    if (plugin.msg_too_big(connection)) return next();

    var username        = plugin.get_spamd_username(connection);
    var headers         = plugin.get_spamd_headers(connection, username);
    var socket          = plugin.get_spamd_socket(next, connection, headers);

    var spamd_response = { headers: {} };
    var state = 'line0';
    var last_header;

    socket.on('line', function (line) {
        connection.logprotocol(plugin, "Spamd C: " + line + ' state=' + state);
        line = line.replace(/\r?\n/, '');
        if (state === 'line0') {
            spamd_response.line0 = line;
            state = 'response';
        }
        else if (state === 'response') {
            if (line.match(/\S/)) {
                var matches = line.match(/Spam: (True|False) ; (-?\d+\.\d) \/ (-?\d+\.\d)/);
                if (matches) {
                    spamd_response.flag = matches[1];
                    spamd_response.score = matches[2];
                    spamd_response.hits = matches[2];  // backwards compat
                    spamd_response.reqd = matches[3];
                    spamd_response.flag = spamd_response.flag === 'True' ? 'Yes' : 'No';
                }
            }
            else {
                state = 'headers';
            }
        }
        else if (state === 'headers') {
            var m = line.match(/^X-Spam-([\x21-\x39\x3B-\x7E]+):\s*(.*)/);
            if (m) {
                connection.logdebug(plugin, "header: " + line);
                last_header = m[1];
                spamd_response.headers[m[1]] = m[2];
                return;
            }
            var fold;
            if (last_header && (fold = line.match(/^(\s+.*)/))) {
                spamd_response.headers[last_header] += "\r\n" + fold[1];
                return;
            }
            last_header = '';
        }
    });

    socket.on('end', function () {
        // Abort if the transaction is gone
        if (!connection.transaction) return next();

        if (spamd_response.headers && spamd_response.headers.Tests) {
            spamd_response.tests = spamd_response.headers.Tests;
        }
        if (spamd_response.tests === undefined) {
            // strip the 'tests' from the X-Spam-Status header
            if (spamd_response.headers && spamd_response.headers.Status) {
                // SpamAssassin appears to have a bug that causes a space not to
                // be added before autolearn= when the header line has been folded.
                // So we modify the regexp here not to match autolearn onwards.
                var tests = /tests=((?:(?!autolearn)[^ ])+)/.exec(spamd_response.headers.Status.replace(/\r?\n\t/g,''));
                if (tests) { spamd_response.tests = tests[1]; }
            }
        }

        // do stuff with the results...
        connection.transaction.notes.spamassassin = spamd_response;

        plugin.fixup_old_headers(connection.transaction);
        plugin.do_header_updates(connection, spamd_response);
        plugin.log_results(connection, spamd_response);

        var exceeds_err = plugin.score_too_high(connection, spamd_response);
        if (exceeds_err) return next(DENY, exceeds_err);

        plugin.munge_subject(connection, spamd_response.score);

        return next();
    });
};

exports.fixup_old_headers = function (transaction) {
    var plugin = this;
    var action = plugin.cfg.main.old_headers_action;
    var headers = transaction.notes.spamassassin.headers;

    var key;
    switch (action) {
        case "keep":
            break;
        case "drop":
            for (key in headers) {
                if (!key) continue;
                transaction.remove_header('X-Spam-' + key);
            }
            break;
        // case 'rename':
        default:
            for (key in headers) {
                if (!key) continue;
                key = 'X-Spam-' + key;
                var old_val = transaction.header.get(key);
                transaction.remove_header(key);
                if (old_val) {
                    // plugin.logdebug(plugin, "header: " + key + ', ' + old_val);
                    transaction.add_header(key.replace(/^X-/, 'X-Old-'), old_val);
                }
            }
            break;
    }
};

exports.munge_subject = function (connection, score) {
    var plugin = this;
    var munge = plugin.cfg.main.munge_subject_threshold;
    if (!munge) return;
    if (parseFloat(score) < parseFloat(munge)) return;

    var subj = connection.transaction.header.get('Subject');
    var subject_re = new RegExp('^' + utils.regexp_escape(plugin.cfg.main.subject_prefix));
    if (subject_re.test(subj)) return;    // prevent double munge

    connection.transaction.remove_header('Subject');
    connection.transaction.add_header('Subject', plugin.cfg.main.subject_prefix + " " + subj);
};

exports.do_header_updates = function (connection, spamd_response) {
    var plugin = this;
    if (spamd_response.flag === 'Yes') {
        // X-Spam-Flag is added by SpamAssassin
        connection.transaction.remove_header('precedence');
        connection.transaction.add_header('Precedence', 'junk');
    }

    var modern = plugin.cfg.main.modern_status_syntax;
    for (var key in spamd_response.headers) {
        if (!key || key === '' || key === undefined) continue;
        var val = spamd_response.headers[key];
        if (val === undefined) { val = ''; }

        if (key === 'Status' && !modern) {
            var legacy = spamd_response.headers[key].replace(/ score=/,' hits=');
            connection.transaction.add_header('X-Spam-Status', legacy);
            continue;
        }
        connection.transaction.add_header('X-Spam-' + key, val);
    }
};

exports.score_too_high = function (connection, spamd_response) {
    var plugin = this;
    var score = spamd_response.score;
    if (connection.relaying) {
        var rmax = plugin.cfg.main.relay_reject_threshold;
        if (rmax && (score >= rmax)) {
            return "spam score exceeded relay threshold";
        }
    }

    var max = plugin.cfg.main.reject_threshold;
    if (max && (score >= max)) {
        return "spam score exceeded threshold";
    }

    return false;
};

exports.get_spamd_username = function(connection) {
    var plugin = this;

    var user = connection.transaction.notes.spamd_user;  // 1st priority
    if (user && user !== undefined) return user;

    if (!plugin.cfg.main.spamd_user) return 'default';   // when not defined
    user = plugin.cfg.main.spamd_user;

    // Enable per-user SA prefs
    if (user === 'first-recipient') {                // special cases
        return connection.transaction.rcpt_to[0].address();
    }
    if (user === 'all-recipients') {
        throw "Unimplemented";
        // TODO: pass the message through SA for each recipient. Then apply
        // the least strict result to the connection. That is useful when
        // one user blacklists a sender that another user wants to get mail
        // from. If this is something you care about, this is the spot.
    }
    return user;
};

exports.get_spamd_headers = function(connection, username) {
    // http://svn.apache.org/repos/asf/spamassassin/trunk/spamd/PROTOCOL
    var headers = [
        'HEADERS SPAMC/1.3',
        'User: ' + username,
        '',
        'X-Envelope-From: ' + connection.transaction.mail_from.address(),
        'X-Haraka-UUID: ' + connection.transaction.uuid,
    ];
    if (connection.relaying) {
        headers.push('X-Haraka-Relay: true');
    }
    return headers;
};

exports.get_spamd_socket = function(next, connection, headers) {
    var plugin = this;
    // TODO: support multiple spamd backends

    var socket = new sock.Socket();
    socket.is_connected = false;
    var results_timeout = parseInt(plugin.cfg.main.results_timeout) || 300;

    socket.on('connect', function () {
        if (!connection.transaction) {
            socket.end();
            return next();
        }
        this.is_connected = true;
        // Reset timeout
        this.setTimeout(results_timeout * 1000);
        socket.write(headers.join("\r\n") + "\r\n");
        connection.transaction.message_stream.pipe(socket);
    });

    socket.on('error', function (err) {
        connection.logerror(plugin, 'connection failed: ' + err);
        // TODO: optionally DENYSOFT
        // TODO: add a transaction note
        return next();
    });

    socket.on('timeout', function () {
        if (!this.is_connected) {
            connection.logerror(plugin, 'spamd connection timed out');
        }
        else {
            connection.logerror(plugin, 'timeout waiting for results');
        }
        socket.end();
        return next();
    });

    var connect_timeout = parseInt(plugin.cfg.main.connect_timeout) || 30;
    socket.setTimeout(connect_timeout * 1000);

    if (plugin.cfg.main.spamd_socket.match(/\//)) {    // assume unix socket
        socket.connect(plugin.cfg.main.spamd_socket);
    }
    else {
        var hostport = plugin.cfg.main.spamd_socket.split(/:/);
        socket.connect((hostport[1] || 783), hostport[0]);
    }

    return socket;
};

exports.msg_too_big = function(connection) {
    var plugin = this;
    if (!plugin.cfg.main.max_size) return false;

    var size = connection.transaction.data_bytes;

    var max = plugin.cfg.main.max_size;
    if (size <= max) { return false; }
    connection.loginfo(plugin, 'skipping, size ' + utils.prettySize(size) + ' exceeds max: ' + utils.prettySize(max));
    return true;
};

exports.log_results = function(connection, spamd_response) {
    var plugin = this;
    var cfg = plugin.cfg.main;
    connection.loginfo(plugin, "status=" + spamd_response.flag +
          ', score=' + spamd_response.score +
          ', required=' + spamd_response.reqd +
          ', reject=' + ((connection.relaying) ?
             (cfg.relay_reject_threshold || cfg.reject_threshold) : cfg.reject_threshold) +
          ', tests="' + spamd_response.tests + '"');
};
<|endoftext|>


<commit_before>const express = require('express');
const app = express();
const port = 80;

app.use('/*', (req, res) => {
  res.send('Ads Blocked by Firewalla');
});

app.listen(port, () => console.log(`Httpd istening on port ${port}!`))<commit_msg>support https<commit_after>'use strict';

const express = require('express');
const app = express();
const port = 80;
const httpsPort = 443;
const path = require('path');
const certPath = 'extension/httpd';
const fs = require('fs');
const https = require('https');

const httpsOptions = {
    key: fs.readFileSync(path.join(certPath, "domain.key")),
    cert: fs.readFileSync(path.join(certPath, "domain.crt"))
};

app.use('*', (req, res) => {
  let txt = `Ads Blocked by Firewalla: ${req.method} ${req.hostname}${req.originalUrl}`;
  res.send(txt);
});

app.listen(port, () => console.log(`Httpd istening on port ${port}!`));

https.createServer(httpsOptions, app).listen(httpsPort, () => console.log(`Httpd istening on port ${httpsPort}!`));
<|endoftext|>