<commit_before>"use strict"

var express = require('express')
var bodyParser = require('body-parser')
var cookieParser = require('cookie-parser')
var cookieSession = require('cookie-session')
var compress = require('compression')
var path = require('path')
var auth = require('./auth')
var geo = require('./geo')
var validatePin = require('cs-pin-validator')
var crypto = require('crypto')
var helmet = require('helmet')
var openalias = require('cs-openalias')
var cloudflare = require('cloudflare')

module.exports = function (){
  var app = express()

  app.use(requireHTTPS)

  if(isProduction()){
    app.set('trust proxy', true)
    var proxyHost = process.env.PROXY_URL.replace("https://", '').replace('?url=', '')
    app.use(helmet.csp({
      'default-src': ["'self'", 'blob:'],
      'connect-src': [
        "'self'", 'blob:',
        'api.bitcoinaverage.com', 'chain.so', // tickers
        'btc.blockr.io', 'tbtc.blockr.io', 'ltc.blockr.io', 'insight.bitpay.com', 'live.coin.space', // blockchain APIs
        process.env.DB_HOST, proxyHost
      ],
      'font-src': ['coin.space'],
      'img-src': ["'self'", 'data:', 'www.gravatar.com'],
      'style-src': ["'self'", "'unsafe-inline'"],
      'script-src': ["'self'", 'blob:', "'unsafe-eval'"], // http://lists.w3.org/Archives/Public/public-webappsec/2014Apr/0021.html, https://github.com/ractivejs/ractive/issues/285
      reportOnly: false,
      setAllHeaders: false,
      safari5: true
    }))
    app.use(helmet.xssFilter())
    app.use(helmet.nosniff())
    app.use(helmet.xframe('sameorigin'))

    var hundredEightyDaysInMilliseconds = 180 * 24 * 60 * 60 * 1000
    app.use(helmet.hsts({
      maxAge: hundredEightyDaysInMilliseconds,
      includeSubdomains: true
    }))
  }

  var anHour = 1000*60*60
  app.use(bodyParser.urlencoded({extended: true}))
  app.use(bodyParser.json())
  app.use(cookieParser(process.env.COOKIE_SALT))
  app.use(cookieSession({
    signed: false,
    overwrite: false,
    maxAge: anHour,
    httpOnly: true,
    secure: isProduction()
  }))
  app.use(compress())

  var cacheControl = isProduction() ? { maxAge: anHour } : null
  app.use(express.static(path.join(__dirname, '..', 'build'), cacheControl))

  app.post('/register', validateAuthParams(false), function(req, res) {
    var name = req.body.wallet_id
    auth.register(name, req.body.pin, req.body.phone, req.body.passphrase, function(err, token){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      setCookie(req, name, function(){
        console.log('registered wallet %s', name)
        res.status(200).send(token)
      })
    })
  })

  app.post('/login', validateAuthParams(true), function(req, res) {
    var name = req.body.wallet_id
    auth.login(name, req.body.pin, function(err, token){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      setCookie(req, name, function(){
        console.log('authenticated wallet %s', name)
        res.status(200).send(token)
      })
    })
  })

  app.get('/exist', function(req, res){
    var name = req.query.wallet_id
    if (!name) return res.status(400).json({error: 'Bad request'});

    auth.exist(name, function(err, userExist){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      res.status(200).send(userExist)
    })
  })

  app.get('/openalias', function(req, res) {
    var hostname = req.query.hostname
    if (!hostname) return res.status(400).json({error: 'Bad request'});
    openalias.resolve(hostname, function(err, address, name) {
      if(err) return res.status(400).send(err)
      res.status(200).send({address: address, name: name})
    })
  })

  app.post('/username', restrict, function(req, res) {
    var id = req.body.id
    var username = req.body.username
    var address = req.body.address
    if (!username || !address) return res.status(400).json({error: 'Bad request'});

    auth.setUsername(id, username, address, function(err, alias, username) {
      if(err) return res.status(400).send(err)
      res.status(200).send({alias: alias, username: username})
    })
  })

  app.delete('/pin', restrict, function(req, res) {
    var id = req.body.id
    var pin = req.body.pin

    auth.disablePin(id, pin, function(err){
      if(err) return res.status(400).send(err)
      res.status(200).send()
    })
  })

  app.post('/location', function(req, res) {
    var args = prepareGeoData(req, res)

    args.push(function(err) {
      if(err) return res.status(400).json(err);
      res.status(201).send()
    })

    geo.save.apply(null, args)
  })

  app.put('/location', function(req, res) {
    var args = prepareGeoData(req, res)
    args.push(function(err, results) {
      if(err) return res.status(400).json(err)
      res.status(200).json(results)
    })

    geo.search.apply(null, args)
  })

  function prepareGeoData(req, res){
    var data = req.body

    var lat = data.lat
    var lon = data.lon
    delete data.lat
    delete data.lon

    var id = req.session.tmpSessionID
    if(!id) {
      id = crypto.randomBytes(16).toString('base64')
      req.session.tmpSessionID = id
    }
    data.id = id

    return [lat, lon, data]
  }

  app.delete('/location', function(req, res) {
    geo.remove(req.session.tmpSessionID)
    res.status(200).send()
  })

  app.post('/purge', function(req, res){
    if (req.query.token === process.env.CLOUDFLARE_TOKEN) {
      cloudflare.createClient({
        email: process.env.CLOUDFLARE_EMAIL,
        token: process.env.CLOUDFLARE_TOKEN
      }).clearCache(process.env.CLOUDFLARE_DOMAIN, '1', function(err) {
        if(err) return res.status(400).send(err)
        res.status(200).send()
      })
    } else {
      return res.status(400).json({error: 'Bad request'})
    }
  })

  app.use(function(err, req, res, next){
    console.error(err.stack);
    res.status(500).send('Oops! something went wrong.');
  })

  app.use(function(req, res, next) {
    res.status(404).send('Oops! page not found.');
  })

  function validateAuthParams(allowMissingPin) {
    return function (req, res, next) {
      if (!req.body.wallet_id || !validatePin(req.body.pin, allowMissingPin)) {
        return res.status(400).json({error: 'Bad request'})
      }

      next()
    }
  }

  function restrict(req, res, next) {
    var session_id = req.session.wallet_id
    if (session_id && session_id === req.body.id) {
      next()
    } else {
      return res.status(401).send()
    }
  }

  function setCookie(req, wallet_id, callback){
    req.session.wallet_id = wallet_id
    callback()
  }

  function requireHTTPS(req, res, next) {
    var herokuForwardedFromHTTPS = req.headers['x-forwarded-proto'] === 'https'
    if (!herokuForwardedFromHTTPS && isProduction()) {
      return res.redirect('https://' + req.get('host') + req.url)
    }
    next()
  }

  function isProduction(){
    return process.env.NODE_ENV === 'production'
  }
  return app
}

<commit_msg>Update express.js<commit_after>"use strict"

var express = require('express')
var bodyParser = require('body-parser')
var cookieParser = require('cookie-parser')
var cookieSession = require('cookie-session')
var compress = require('compression')
var path = require('path')
var auth = require('./auth')
var geo = require('./geo')
var validatePin = require('cs-pin-validator')
var crypto = require('crypto')
var helmet = require('helmet')
var openalias = require('cs-openalias')
var cloudflare = require('cloudflare')

module.exports = function (){
  var app = express()

  app.use(requireHTTPS)

  if(isProduction()){
    app.set('trust proxy', true)
    var proxyHost = process.env.PROXY_URL.replace("https://", '').replace('?url=', '')
    app.use(helmet.csp({
      'default-src': ["'self'", 'blob:'],
      'connect-src': [
        "'self'", 'blob:',
        'api.bitcoinaverage.com', 'chain.so', // tickers
        'btc.blockr.io', 'tbtc.blockr.io', 'ltc.blockr.io', 'insight.bitpay.com', 'live.coin.space', // blockchain APIs
        process.env.DB_HOST, proxyHost
      ],
      'font-src': ['self'],
      'img-src': ["'self'", 'data:', 'www.gravatar.com'],
      'style-src': ["'self'", "'unsafe-inline'"],
      'script-src': ["'self'", 'blob:', "'unsafe-eval'"], // http://lists.w3.org/Archives/Public/public-webappsec/2014Apr/0021.html, https://github.com/ractivejs/ractive/issues/285
      reportOnly: false,
      setAllHeaders: false,
      safari5: true
    }))
    app.use(helmet.xssFilter())
    app.use(helmet.nosniff())
    app.use(helmet.xframe('sameorigin'))

    var hundredEightyDaysInMilliseconds = 180 * 24 * 60 * 60 * 1000
    app.use(helmet.hsts({
      maxAge: hundredEightyDaysInMilliseconds,
      includeSubdomains: true
    }))
  }

  var anHour = 1000*60*60
  app.use(bodyParser.urlencoded({extended: true}))
  app.use(bodyParser.json())
  app.use(cookieParser(process.env.COOKIE_SALT))
  app.use(cookieSession({
    signed: false,
    overwrite: false,
    maxAge: anHour,
    httpOnly: true,
    secure: isProduction()
  }))
  app.use(compress())

  var cacheControl = isProduction() ? { maxAge: anHour } : null
  app.use(express.static(path.join(__dirname, '..', 'build'), cacheControl))

  app.post('/register', validateAuthParams(false), function(req, res) {
    var name = req.body.wallet_id
    auth.register(name, req.body.pin, req.body.phone, req.body.passphrase, function(err, token){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      setCookie(req, name, function(){
        console.log('registered wallet %s', name)
        res.status(200).send(token)
      })
    })
  })

  app.post('/login', validateAuthParams(true), function(req, res) {
    var name = req.body.wallet_id
    auth.login(name, req.body.pin, function(err, token){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      setCookie(req, name, function(){
        console.log('authenticated wallet %s', name)
        res.status(200).send(token)
      })
    })
  })

  app.get('/exist', function(req, res){
    var name = req.query.wallet_id
    if (!name) return res.status(400).json({error: 'Bad request'});

    auth.exist(name, function(err, userExist){
      if(err) {
        console.error('error', err)
        return res.status(400).send(err)
      }

      res.status(200).send(userExist)
    })
  })

  app.get('/openalias', function(req, res) {
    var hostname = req.query.hostname
    if (!hostname) return res.status(400).json({error: 'Bad request'});
    openalias.resolve(hostname, function(err, address, name) {
      if(err) return res.status(400).send(err)
      res.status(200).send({address: address, name: name})
    })
  })

  app.post('/username', restrict, function(req, res) {
    var id = req.body.id
    var username = req.body.username
    var address = req.body.address
    if (!username || !address) return res.status(400).json({error: 'Bad request'});

    auth.setUsername(id, username, address, function(err, alias, username) {
      if(err) return res.status(400).send(err)
      res.status(200).send({alias: alias, username: username})
    })
  })

  app.delete('/pin', restrict, function(req, res) {
    var id = req.body.id
    var pin = req.body.pin

    auth.disablePin(id, pin, function(err){
      if(err) return res.status(400).send(err)
      res.status(200).send()
    })
  })

  app.post('/location', function(req, res) {
    var args = prepareGeoData(req, res)

    args.push(function(err) {
      if(err) return res.status(400).json(err);
      res.status(201).send()
    })

    geo.save.apply(null, args)
  })

  app.put('/location', function(req, res) {
    var args = prepareGeoData(req, res)
    args.push(function(err, results) {
      if(err) return res.status(400).json(err)
      res.status(200).json(results)
    })

    geo.search.apply(null, args)
  })

  function prepareGeoData(req, res){
    var data = req.body

    var lat = data.lat
    var lon = data.lon
    delete data.lat
    delete data.lon

    var id = req.session.tmpSessionID
    if(!id) {
      id = crypto.randomBytes(16).toString('base64')
      req.session.tmpSessionID = id
    }
    data.id = id

    return [lat, lon, data]
  }

  app.delete('/location', function(req, res) {
    geo.remove(req.session.tmpSessionID)
    res.status(200).send()
  })

  app.post('/purge', function(req, res){
    if (req.query.token === process.env.CLOUDFLARE_TOKEN) {
      cloudflare.createClient({
        email: process.env.CLOUDFLARE_EMAIL,
        token: process.env.CLOUDFLARE_TOKEN
      }).clearCache(process.env.CLOUDFLARE_DOMAIN, '1', function(err) {
        if(err) return res.status(400).send(err)
        res.status(200).send()
      })
    } else {
      return res.status(400).json({error: 'Bad request'})
    }
  })

  app.use(function(err, req, res, next){
    console.error(err.stack);
    res.status(500).send('Oops! something went wrong.');
  })

  app.use(function(req, res, next) {
    res.status(404).send('Oops! page not found.');
  })

  function validateAuthParams(allowMissingPin) {
    return function (req, res, next) {
      if (!req.body.wallet_id || !validatePin(req.body.pin, allowMissingPin)) {
        return res.status(400).json({error: 'Bad request'})
      }

      next()
    }
  }

  function restrict(req, res, next) {
    var session_id = req.session.wallet_id
    if (session_id && session_id === req.body.id) {
      next()
    } else {
      return res.status(401).send()
    }
  }

  function setCookie(req, wallet_id, callback){
    req.session.wallet_id = wallet_id
    callback()
  }

  function requireHTTPS(req, res, next) {
    var herokuForwardedFromHTTPS = req.headers['x-forwarded-proto'] === 'https'
    if (!herokuForwardedFromHTTPS && isProduction()) {
      return res.redirect('https://' + req.get('host') + req.url)
    }
    next()
  }

  function isProduction(){
    return process.env.NODE_ENV === 'production'
  }
  return app
}

<|endoftext|>


<commit_before>angular.module('aurora.controllers', [])

.controller('DashCtrl', function($scope, $push, $geolocation, $kpAPI) {
    $scope.requestPush         = function() {
    $push.requestTestPushNotification();
    }

    $scope.initPush            = function() {
    $push.initPushNotifications();
    }

    $scope.showGeoLocationInfo = function() {
        $geolocation.showGeoLocationInfo();
    }

    console.log($kpAPI.getForecast());
})

.controller('SettingsCtrl', function($scope, $localstorage, $ionicPopover) {
    $scope.loadDefaults = function() {
        $scope.alerts      = true;
        $scope.kpTrigger   = 1;
		$scope.daytime	   = false;
        $scope.gps         = false;
        $scope.zip         = 90210;
    }

    $scope.loadSettings = function() {
        $scope.alerts      = $localstorage.get('alerts');
        $scope.kpTrigger   = $localstorage.get('kpTrigger');
		$scope.daytime	   = $localstorage.get('daytime');
        $scope.gps         = $localstorage.get('gps');
        $scope.zip         = $localstorage.get('zip');

        if (typeof $scope.alerts == 'undefined') {
            $scope.loadDefaults();
            $scope.saveAllSettings();
        };
    }

    $scope.saveAllSettings = function() {
        $localstorage.set('alerts', $scope.alerts);
        $localstorage.set('kpTrigger', $scope.kpTrigger);
		$localstorage.set('daytime', $scope.daytime);
        $localstorage.set('gps', $scope.gps);
        $localstorage.set('zip', $scope.zip);
    }

    $scope.outputSettings = function(asAlert) {
        data = {'alerts' : $scope.alerts,
                'kpTrigger' : $scope.kpTrigger,
				'daytime' : $scope.daytime,
                'gps' : $scope.gps,
                'zip' : $scope.zip};

        if(asAlert)
            alert(data);
        else
            console.log(data);
    }

    $scope.geolocationToggled = function() {
        $localstorage.set('gps', !$scope.gps);
        console.log('AURORA: GPS toggled!');
    }

    $scope.loadSettings();
    $scope.outputSettings(true);

    $ionicPopover.fromTemplateUrl('popover-lkpa.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplkpa = popover;
    });

    $ionicPopover.fromTemplateUrl('popover-lDay.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplDay = popover;
    });

    $ionicPopover.fromTemplateUrl('popover-lAlert.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplAlert = popover;
    });
})

.controller('AboutCtrl', function($scope) {})

.controller('AllskyCtrl', function($scope) {})

.controller('NotificationCtrl', function($scope, $push) {

});<commit_msg>Changed to output to console by default.<commit_after>angular.module('aurora.controllers', [])

.controller('DashCtrl', function($scope, $push, $geolocation, $kpAPI) {
    $scope.requestPush         = function() {
    $push.requestTestPushNotification();
    }

    $scope.initPush            = function() {
    $push.initPushNotifications();
    }

    $scope.showGeoLocationInfo = function() {
        $geolocation.showGeoLocationInfo();
    }

    console.log($kpAPI.getForecast());
})

.controller('SettingsCtrl', function($scope, $localstorage, $ionicPopover) {
    $scope.loadDefaults = function() {
        $scope.alerts      = true;
        $scope.kpTrigger   = 1;
		$scope.daytime	   = false;
        $scope.gps         = false;
        $scope.zip         = 90210;
    }

    $scope.loadSettings = function() {
        $scope.alerts      = $localstorage.get('alerts');
        $scope.kpTrigger   = $localstorage.get('kpTrigger');
		$scope.daytime	   = $localstorage.get('daytime');
        $scope.gps         = $localstorage.get('gps');
        $scope.zip         = $localstorage.get('zip');

        if (typeof $scope.alerts == 'undefined') {
            $scope.loadDefaults();
            $scope.saveAllSettings();
        };
    }

    $scope.saveAllSettings = function() {
        $localstorage.set('alerts', $scope.alerts);
        $localstorage.set('kpTrigger', $scope.kpTrigger);
		$localstorage.set('daytime', $scope.daytime);
        $localstorage.set('gps', $scope.gps);
        $localstorage.set('zip', $scope.zip);
    }

    $scope.outputSettings = function(asAlert) {
        data = {'alerts' : $scope.alerts,
                'kpTrigger' : $scope.kpTrigger,
				'daytime' : $scope.daytime,
                'gps' : $scope.gps,
                'zip' : $scope.zip};

        if(asAlert)
            alert(data);
        else
            console.log(data);
    }

    $scope.geolocationToggled = function() {
        $localstorage.set('gps', !$scope.gps);
        console.log('AURORA: GPS toggled!');
    }

    $scope.loadSettings();
    $scope.outputSettings(false);

    $ionicPopover.fromTemplateUrl('popover-lkpa.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplkpa = popover;
    });

    $ionicPopover.fromTemplateUrl('popover-lDay.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplDay = popover;
    });

    $ionicPopover.fromTemplateUrl('popover-lAlert.html', {
        scope: $scope,
    }).then(function(popover) {
        $scope.poplAlert = popover;
    });
})

.controller('AboutCtrl', function($scope) {})

.controller('AllskyCtrl', function($scope) {})

.controller('NotificationCtrl', function($scope, $push) {

});<|endoftext|>


<commit_before>var goog = require('googleapis');
var OAuth2 = goog.auth.OAuth2;
var yt = goog.youtube({version: 'v3'})
var moment = require('moment');

var apiKey = "";
module.exports.init = function(b) {
	b.getConfig("google.json", function(err, conf) {
		if(!err) {
			apiKey = conf.apiKey
		}
	});
};

var ytRegex =  /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i;

function formatPt50(pt50) {
	var duration = moment.duration(pt50);
	var hours   = duration.hours()
	var minutes = duration.minutes()
	var seconds = duration.seconds()
	if (hours   < 10) {hours   = "0"+hours;}
	if (minutes < 10) {minutes = "0"+minutes;}
	if (seconds < 10) {seconds = "0"+seconds;}
	var time    = hours+':'+minutes+':'+seconds;
	return time;
}

function likePerecent(vid) {
	try {
		var like = parseInt(vid.statistics.likeCount, 10);
		var hate = parseInt(vid.statistics.dislikeCount, 10);
		return (like / (like + hate) * 100).toString().substr(0, 4) + "%";
	} catch(ex) {
		console.log("Ty google for giving me this video which is screwed", vid)
		return "?%";
	}
}

function sayInfo(vid, cb, sayUrl) {
  var url = 'http://youtu.be/' + vid.id;
  cb((sayUrl ? (url + " ") : '') + vid.snippet.title, '-', formatPt50(vid.contentDetails.duration), (vid.statistics.viewCount ? '- ' + vid.statistics.viewCount + ' views' : '') + "(" + likePerecent(vid) + ") - " + vid.snippet.channelTitle);
}

function sayIdInfo(id, cb, sayUrl) {
	yt.videos.list({auth: apiKey, id: id, part: "snippet,statistics,contentDetails"}, function(err, results) {
		if(results.items.length > 0) {
			sayInfo(results.items[0], cb, sayUrl)
		}
	});
}

module.exports.url = function(url, reply) {
	if(apiKey == "") return;
	var m;
	if((m = ytRegex.exec(url))) {
		var id = m[1];
		sayIdInfo(id, reply, false);
	}
};

module.exports.commands = ['yt', 'youtube'];
module.exports.run = function(remainder, parts, reply, command, from, to, text, raw) {
	if(apiKey == "") return;
	yt.search.list({auth: apiKey, part: "id", type: "video", q: remainder, maxResults: 1}, function(err,res) {
		if(err || res.items.length < 1) return reply("No results");
		var vidId = res.items[0].id.videoId;
		sayIdInfo(vidId, reply, true);
  });
};
<commit_msg>modules/yt: dodge a divide by zero<commit_after>var goog = require('googleapis');
var OAuth2 = goog.auth.OAuth2;
var yt = goog.youtube({version: 'v3'});
var moment = require('moment');

var apiKey = "";
module.exports.init = function(b) {
	b.getConfig("google.json", function(err, conf) {
		if(!err) {
			apiKey = conf.apiKey;
		}
	});
};

var ytRegex =  /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i;

function formatPt50(pt50) {
	var duration = moment.duration(pt50);
	var hours   = duration.hours();
	var minutes = duration.minutes();
	var seconds = duration.seconds();
	if (hours   < 10) {hours   = "0"+hours;}
	if (minutes < 10) {minutes = "0"+minutes;}
	if (seconds < 10) {seconds = "0"+seconds;}
	var time    = hours+':'+minutes+':'+seconds;
	return time;
}

function likePercent(vid) {
	try {
		var like = parseInt(vid.statistics.likeCount, 10);
		var hate = parseInt(vid.statistics.dislikeCount, 10);
		if(hate === 0) {
			// divide by 0
			if(like === 0) {
				return "N/A";
			}
			return "100%";
		}
		return (like / (like + hate) * 100).toString().substr(0, 4) + "%";
	} catch(ex) {
		console.log("Ty google for giving me this video which is screwed", vid);
		return "?%";
	}
}

function sayInfo(vid, cb, sayUrl) {
  var url = 'http://youtu.be/' + vid.id;
  cb((sayUrl ? (url + " ") : '') + vid.snippet.title, '-', formatPt50(vid.contentDetails.duration), (vid.statistics.viewCount ? '- ' + vid.statistics.viewCount + ' views' : '') + "(" + likePercent(vid) + ") - " + vid.snippet.channelTitle);
}

function sayIdInfo(id, cb, sayUrl) {
	yt.videos.list({auth: apiKey, id: id, part: "snippet,statistics,contentDetails"}, function(err, results) {
		if(results.items.length > 0) {
			sayInfo(results.items[0], cb, sayUrl);
		}
	});
}

module.exports.url = function(url, reply) {
	if(apiKey === "") return;
	var m;
	if((m = ytRegex.exec(url))) {
		var id = m[1];
		sayIdInfo(id, reply, false);
	}
};

module.exports.commands = ['yt', 'youtube'];
module.exports.run = function(remainder, parts, reply, command, from, to, text, raw) {
	if(apiKey === "") return;
	yt.search.list({auth: apiKey, part: "id", type: "video", q: remainder, maxResults: 1}, function(err,res) {
		if(err || res.items.length < 1) return reply("No results");
		var vidId = res.items[0].id.videoId;
		sayIdInfo(vidId, reply, true);
  });
};
<|endoftext|>


<commit_before>const LANGUAGE_COLORS = {
  Scala: '#BB0017',
  Clojure: '#00AA00',
  JS: '#CCAA00',
  VB: '#663300',
  'C#': '#7600BC',
  Go: '#996633',
  HTML5: '#FF0032',
  Python: '#0000CC',
  'C++': '#FF0099',
  Groovy: '#00C92',
  Java: '#006600',
  ObjectiveC: '#FF8C00',
  CSS: '#0099FF',
  DEFAULT: '#EEE'
};

export default LANGUAGE_COLORS;
<commit_msg>Fix Groovy color.<commit_after>const LANGUAGE_COLORS = {
  Scala: '#BB0017',
  Clojure: '#00AA00',
  JS: '#CCAA00',
  VB: '#663300',
  'C#': '#7600BC',
  Go: '#996633',
  HTML5: '#FF0032',
  Python: '#0000CC',
  'C++': '#FF0099',
  Groovy: '#00CC92',
  Java: '#006600',
  ObjectiveC: '#FF8C00',
  CSS: '#0099FF',
  DEFAULT: '#EEE'
};

export default LANGUAGE_COLORS;
<|endoftext|>


<commit_before>import _ from 'lodash'

function pathFinder (valueObj, prevPath) {
  return function (path) {
    if (!_.isArray(path)) {
      path = path.split('.').reverse()
    }
    let nextInPath = _.last(path)

    if (nextInPath === '') {
      path.pop()
      if (_.last(path) === '') {
        path.pop()
        path.push(path.pop().replace('/', ''))
        return prevPath(path)
      } else {
        path.push(path.pop().replace('/', ''))
      }
    }
    return _.get(valueObj, path.reverse().join('.'))
  }
}

// (value, condition)->boolean
function meetsCondition (value, condition) {
  let isConditionMet = false

  if (condition.equals) {
    isConditionMet = isConditionMet || _.isEqual(condition.equals, value)
  }

  if (condition.greaterThan) {
    isConditionMet = isConditionMet || value > condition.greaterThan
  }

  if (condition.lessThan) {
    isConditionMet = isConditionMet || value < condition.lessThan
  }

  return isConditionMet
}

function convertConditionalProperties (model, value, getPreviousValue) {
  if (model.type !== 'object' && model.type !== 'array' && model.properties === undefined) {
    return model
  }

  let retModel = _.cloneDeep(model)
  if (model.type === 'array' && _.isArray(value)) {
    let itemSchemas = []
    // Deep version of _.uniq
    const potentialSchemas = _.map(value, function (val) {
      return convertConditionalProperties(model.items, val, getPreviousValue)
    })
    _.each(potentialSchemas, function (schema) {
      if (!_.some(itemSchemas, _.partial(_.isEqual, schema))) {
        itemSchemas.push(schema)
      }
    })
    if (itemSchemas.length > 1) {
      retModel.items = {anyOf: itemSchemas}
    } else {
      retModel.items = itemSchemas[0]
    }
  }

  let depsMet = {}
  let props = {}

  const getValue = pathFinder(value, getPreviousValue)

  _.each(retModel.properties, function (subSchema, propName) {
    retModel.properties[propName] = convertConditionalProperties(subSchema, _.get(value, propName), pathFinder(value, getValue))
  })
  let conditionalProperties = _.transform(model.properties, function (result, schema, key) {
    if (schema.conditions) {
      result[key] = schema
    }
  })
  _.each(conditionalProperties, function (depSchema, key) {
    depsMet[key] = _.some(depSchema.conditions, function (enableConditions) {
      const hasDependencyMet = _.some(enableConditions.if, function (conditionList) {
        return _.every(conditionList, function (conditionValue, dependencyKey) {
          const dependencyValue = getValue(dependencyKey)
          return meetsCondition(dependencyValue, conditionValue)
        })
      })
      if (hasDependencyMet && enableConditions.then !== undefined) {
        props[key] = _.cloneDeep(enableConditions.then)
      }
      return hasDependencyMet
    })
  })
  _.each(depsMet, function (dependencyMet, depName) {
    const baseSchema = retModel.properties[depName]
    if (dependencyMet && !baseSchema.set || !dependencyMet && baseSchema.set) {
      retModel.properties[depName] = _.omit(_.defaults(props[depName] || {}, baseSchema), ['conditions', 'set'])
    } else {
      delete retModel.properties[depName]
    }
  })

  return retModel
}

export default convertConditionalProperties
<commit_msg>Array item schema converted when value is undefined.<commit_after>import _ from 'lodash'

function pathFinder (valueObj, prevPath) {
  return function (path) {
    if (!_.isArray(path)) {
      path = path.split('.').reverse()
    }
    let nextInPath = _.last(path)

    if (nextInPath === '') {
      path.pop()
      if (_.last(path) === '') {
        path.pop()
        path.push(path.pop().replace('/', ''))
        return prevPath(path)
      } else {
        path.push(path.pop().replace('/', ''))
      }
    }
    return _.get(valueObj, path.reverse().join('.'))
  }
}

// (value, condition)->boolean
function meetsCondition (value, condition) {
  let isConditionMet = false

  if (condition.equals) {
    isConditionMet = isConditionMet || _.isEqual(condition.equals, value)
  }

  if (condition.greaterThan) {
    isConditionMet = isConditionMet || value > condition.greaterThan
  }

  if (condition.lessThan) {
    isConditionMet = isConditionMet || value < condition.lessThan
  }

  return isConditionMet
}

function convertConditionalProperties (model, value, getPreviousValue) {
  if (model.type !== 'object' && model.type !== 'array' && model.properties === undefined) {
    return model
  }

  let retModel = _.cloneDeep(model)
  if (model.type === 'array') {
    if (_.isArray(value)) {
      let itemSchemas = []
      // Deep version of _.uniq
      const potentialSchemas = _.map(value, function (val) {
        return convertConditionalProperties(model.items, val, getPreviousValue)
      })
      _.each(potentialSchemas, function (schema) {
        if (!_.some(itemSchemas, _.partial(_.isEqual, schema))) {
          itemSchemas.push(schema)
        }
      })
      if (itemSchemas.length > 1) {
        retModel.items = {anyOf: itemSchemas}
      } else {
        retModel.items = itemSchemas[0]
      }
    } else if (value === undefined) {
      retModel.items = convertConditionalProperties(model.items, value, getPreviousValue)
    }
  }

  let depsMet = {}
  let props = {}

  const getValue = pathFinder(value, getPreviousValue)

  _.each(retModel.properties, function (subSchema, propName) {
    retModel.properties[propName] = convertConditionalProperties(subSchema, _.get(value, propName), pathFinder(value, getValue))
  })
  let conditionalProperties = _.transform(model.properties, function (result, schema, key) {
    if (schema.conditions) {
      result[key] = schema
    }
  })
  _.each(conditionalProperties, function (depSchema, key) {
    depsMet[key] = _.some(depSchema.conditions, function (enableConditions) {
      const hasDependencyMet = _.some(enableConditions.if, function (conditionList) {
        return _.every(conditionList, function (conditionValue, dependencyKey) {
          const dependencyValue = getValue(dependencyKey)
          return meetsCondition(dependencyValue, conditionValue)
        })
      })
      if (hasDependencyMet && enableConditions.then !== undefined) {
        props[key] = _.cloneDeep(enableConditions.then)
      }
      return hasDependencyMet
    })
  })
  _.each(depsMet, function (dependencyMet, depName) {
    const baseSchema = retModel.properties[depName]
    if (dependencyMet && !baseSchema.set || !dependencyMet && baseSchema.set) {
      retModel.properties[depName] = _.omit(_.defaults(props[depName] || {}, baseSchema), ['conditions', 'set'])
    } else {
      delete retModel.properties[depName]
    }
  })

  return retModel
}

export default convertConditionalProperties
<|endoftext|>


<commit_before>const DigitTicker = (() => {
    let el_container,
        el_peek,
        el_peek_box,
        el_mask,
        total_tick_count,
        contract_status,
        type,
        current_spot;
    let style_offset_correction = 5;

    let is_lazy_numbers = false;

    const array_of_digits         = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    const isBarrierMissing = (contract_type, barrier) => contract_type !== 'DIGITDIFF' && contract_type !== 'DIGITMATCH' && !barrier;

    const init = (container_id, contract_type, barrier, tick_count, status = 'open') => {
        if (isBarrierMissing(contract_type, barrier)) {
            is_lazy_numbers = true;
        }
        contract_status      = status;
        total_tick_count     = tick_count;
        type                 = contract_type;
        current_spot         = '-';
        el_container         = document.querySelector(`#${container_id}`);
        populateContainer(el_container);
        if (!is_lazy_numbers) {
            highlightWinningNumbers(getWinningNumbers(contract_type, barrier));
        }
        observeResize();
    };

    const populateContainer = (container_element) => {
        // remove previous elements and start fresh.
        while (container_element && container_element.firstChild) {
            container_element.removeChild(container_element.firstChild);
        }

        const temp_epoch_el = document.createElement('div');
        temp_epoch_el.classList.add('epoch');
        const temp_peek_box_el = document.createElement('div');
        temp_peek_box_el.classList.add('peek-box');
        if (contract_status === 'won') {
            temp_peek_box_el.classList.add('digit-winning');
        }
        if (contract_status === 'lost') {
            temp_peek_box_el.classList.add('digit-losing');
        }

        const temp_digits_el = document.createElement('div');
        temp_digits_el.classList.add('digits');
        array_of_digits.forEach(digit => {
            const digit_el = document.createElement('div');
            digit_el.classList.add('digit', `digit-${digit}`);
            digit_el.appendChild(document.createTextNode(digit));
            temp_digits_el.appendChild(digit_el);
        });

        const temp_mask_el = document.createElement('div');
        temp_mask_el.classList.add('mask');
        temp_mask_el.append(document.createTextNode('0 / 0'));

        const temp_peek_el = document.createElement('div');
        temp_peek_el.classList.add('peek');
        // grid peek-box element definition
        const topleft_el = document.createElement('div');
        topleft_el.classList.add('topleft');
        const top_el = document.createElement('div');
        top_el.classList.add('top');
        const topright_el = document.createElement('div');
        topright_el.classList.add('topright');
        const left_el = document.createElement('div');
        left_el.classList.add('left');
        const right_el = document.createElement('div');
        right_el.classList.add('right');
        const bottomleft_el = document.createElement('div');
        bottomleft_el.classList.add('bottomleft');
        const bottom_el = document.createElement('div');
        bottom_el.classList.add('bottom');
        const bottomright_el = document.createElement('div');
        bottomright_el.classList.add('bottomright');
        temp_peek_box_el.appendChild(topleft_el);
        temp_peek_box_el.appendChild(top_el);
        temp_peek_box_el.appendChild(topright_el);
        temp_peek_box_el.appendChild(left_el);
        temp_peek_box_el.appendChild(right_el);
        temp_peek_box_el.appendChild(bottomright_el);
        temp_peek_box_el.appendChild(bottomleft_el);
        temp_peek_box_el.appendChild(bottom_el);
        temp_peek_box_el.appendChild(temp_mask_el);
        temp_peek_box_el.appendChild(temp_peek_el);

        const fragment = document.createDocumentFragment();
        fragment.appendChild(temp_epoch_el);
        fragment.appendChild(temp_peek_box_el);
        fragment.appendChild(temp_digits_el);
        container_element.appendChild(fragment);
        container_element.classList.add('invisible');
    };

    // adjust box sizes for mobile
    const adjustBoxSizes = () => {
        if (el_container.offsetWidth < 360) {
            style_offset_correction = 6;
        }
    };

    // Detect winning numbers against the barrier with the given contract type.
    const getWinningNumbers = (contract_type, barrier) => {
        switch (contract_type) {
            case 'DIGITOVER':
                return array_of_digits.filter(digit => +digit > +barrier);
            case 'DIGITUNDER':
                return array_of_digits.filter(digit => +digit < +barrier);
            case 'DIGITMATCH':
                return array_of_digits.filter(digit => +digit === +barrier);
            case 'DIGITDIFF':
                return array_of_digits.filter(digit => +digit !== +barrier);
            case 'DIGITODD':
                return array_of_digits.filter(digit => +digit % 2 !== 0);
            case 'DIGITEVEN':
                return array_of_digits.filter(digit => +digit % 2 === 0);
            default:
                throw new Error('Cannot Determine Winning numbers.');
        }
    };

    const highlightWinningNumbers = (winning_numbers) => {
        winning_numbers.forEach(digit => {
            const element = el_container.querySelector(`.digit-${digit}`);
            element.classList.remove('digit-losing');
            element.classList.add('digit-winning');
        });
    };

    const observeResize = () => {
        window.onresize = () => {
            if (el_peek_box) {
                adjustBoxSizes();
                el_peek_box.setAttribute('style', `transform: translateX(${calculateOffset()}px)`);
            }
        };
    };

    // Calculate peek-box left offset.
    const calculateOffset = () => {
        const left_offset = document.querySelector(`.digit-${current_spot}`).offsetLeft;
        return left_offset - style_offset_correction;
    };

    const markAsLost = () => {
        if (!el_peek_box || !el_peek) {
            setElements();
        }
        el_peek.classList.remove('digit-winning', 'digit-running');
        el_peek_box.classList.remove('digit-winning', 'digit-running');
        el_peek.classList.add('digit-losing');
        el_peek_box.classList.add('digit-losing');
    };

    const markDigitAsWon = (digit) => {
        el_container.querySelector(`.digit-${digit}`).classList.add('digit-won');
    };

    const markDigitAsLost = (digit) => {
        el_container.querySelector(`.digit-${digit}`).classList.add('digit-lost');
    };

    const markAsWon = () => {
        if (!el_peek_box || !el_peek) {
            setElements();
        }
        el_peek_box.classList.remove('digit-losing', 'digit-running');
        el_peek_box.classList.add('digit-winning');
        el_peek.classList.remove('digit-losing', 'digit-running');
        el_peek.classList.add('digit-winning');
    };

    const setElements = () => {
        el_peek     = el_container.querySelector('.peek');
        el_peek_box = el_container.querySelector('.peek-box');
        el_mask     = el_peek_box.querySelector('.peek-box > .mask');
    };

    const update = (current_tick_count, { quote, epoch, barrier }) => {
        if (!isBarrierMissing(type, barrier) && is_lazy_numbers) {
            highlightWinningNumbers(getWinningNumbers(type, barrier));
            is_lazy_numbers = false;
        }
        setElements(epoch);
        el_container.classList.remove('invisible');
        adjustBoxSizes();
        current_spot = quote.substr(-1);

        el_mask.innerText = `${current_tick_count} / ${total_tick_count}`;

        el_peek_box.classList.add('digit-running');
        el_peek.classList.add('digit-running');

        el_peek_box.setAttribute('style', `transform: translateX(${calculateOffset()}px)`);
    };

    const remove = () => {
        window.onresize = null;
        while (el_container && el_container.firstChild) {
            el_container.removeChild(el_container.firstChild);
        }
        if (el_container) el_container.classList.add('invisible');
    };

    const countDecimals = (value) => {
        if (Math.floor(value) !== value) return value.toString().split('.')[1].length || 0;
        return 0;
    };

    const calculateDistance = (old_digit, new_digit) => Math.abs(old_digit - new_digit);

    const countUp = (start, end, duration, element, render) => {
        const decimal_points = countDecimals(start.replace('/,+/', ''));
        const f_start = parseFloat(start.replace(/,+/, ''));
        const range = calculateDistance(f_start, end);
        const step = Math.abs(range / 60);
        const increment = end > f_start ? (1 * step) : (-1 * step);
        let current = f_start;
        let i = 0;

        const renderTick = () => {
            i++;
            current += increment;

            element.innerHTML = render(current.toFixed(decimal_points));

            if (i <= 15) {
                requestAnimationFrame(renderTick);
            } else {
                current = end;
                element.innerHTML = render(current.toFixed(decimal_points));
            }
        };

        requestAnimationFrame(renderTick);
    };

    return {
        init,
        update,
        countUp,
        markAsWon,
        markAsLost,
        markDigitAsLost,
        markDigitAsWon,
        remove,
    };
})();

module.exports = DigitTicker;
<commit_msg>Possible fix for lazy barrier loading<commit_after>const DigitTicker = (() => {
    let el_container,
        el_peek,
        el_peek_box,
        el_mask,
        total_tick_count,
        contract_status,
        type,
        current_spot;
    let style_offset_correction = 5;

    let is_lazy_numbers = false;

    const array_of_digits         = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    const isBarrierMissing = (contract_type, barrier) => contract_type !== 'DIGITEVEN' && contract_type !== 'DIGITODD' && !barrier;

    const init = (container_id, contract_type, barrier, tick_count, status = 'open') => {
        if (isBarrierMissing(contract_type, barrier)) {
            is_lazy_numbers = true;
        }
        contract_status      = status;
        total_tick_count     = tick_count;
        type                 = contract_type;
        current_spot         = '-';
        el_container         = document.querySelector(`#${container_id}`);
        populateContainer(el_container);
        if (!is_lazy_numbers) {
            highlightWinningNumbers(getWinningNumbers(contract_type, barrier));
        }
        observeResize();
    };

    const populateContainer = (container_element) => {
        // remove previous elements and start fresh.
        while (container_element && container_element.firstChild) {
            container_element.removeChild(container_element.firstChild);
        }

        const temp_epoch_el = document.createElement('div');
        temp_epoch_el.classList.add('epoch');
        const temp_peek_box_el = document.createElement('div');
        temp_peek_box_el.classList.add('peek-box');
        if (contract_status === 'won') {
            temp_peek_box_el.classList.add('digit-winning');
        }
        if (contract_status === 'lost') {
            temp_peek_box_el.classList.add('digit-losing');
        }

        const temp_digits_el = document.createElement('div');
        temp_digits_el.classList.add('digits');
        array_of_digits.forEach(digit => {
            const digit_el = document.createElement('div');
            digit_el.classList.add('digit', `digit-${digit}`);
            digit_el.appendChild(document.createTextNode(digit));
            temp_digits_el.appendChild(digit_el);
        });

        const temp_mask_el = document.createElement('div');
        temp_mask_el.classList.add('mask');
        temp_mask_el.append(document.createTextNode('0 / 0'));

        const temp_peek_el = document.createElement('div');
        temp_peek_el.classList.add('peek');
        // grid peek-box element definition
        const topleft_el = document.createElement('div');
        topleft_el.classList.add('topleft');
        const top_el = document.createElement('div');
        top_el.classList.add('top');
        const topright_el = document.createElement('div');
        topright_el.classList.add('topright');
        const left_el = document.createElement('div');
        left_el.classList.add('left');
        const right_el = document.createElement('div');
        right_el.classList.add('right');
        const bottomleft_el = document.createElement('div');
        bottomleft_el.classList.add('bottomleft');
        const bottom_el = document.createElement('div');
        bottom_el.classList.add('bottom');
        const bottomright_el = document.createElement('div');
        bottomright_el.classList.add('bottomright');
        temp_peek_box_el.appendChild(topleft_el);
        temp_peek_box_el.appendChild(top_el);
        temp_peek_box_el.appendChild(topright_el);
        temp_peek_box_el.appendChild(left_el);
        temp_peek_box_el.appendChild(right_el);
        temp_peek_box_el.appendChild(bottomright_el);
        temp_peek_box_el.appendChild(bottomleft_el);
        temp_peek_box_el.appendChild(bottom_el);
        temp_peek_box_el.appendChild(temp_mask_el);
        temp_peek_box_el.appendChild(temp_peek_el);

        const fragment = document.createDocumentFragment();
        fragment.appendChild(temp_epoch_el);
        fragment.appendChild(temp_peek_box_el);
        fragment.appendChild(temp_digits_el);
        container_element.appendChild(fragment);
        container_element.classList.add('invisible');
    };

    // adjust box sizes for mobile
    const adjustBoxSizes = () => {
        if (el_container.offsetWidth < 360) {
            style_offset_correction = 6;
        }
    };

    // Detect winning numbers against the barrier with the given contract type.
    const getWinningNumbers = (contract_type, barrier) => {
        switch (contract_type) {
            case 'DIGITOVER':
                return array_of_digits.filter(digit => +digit > +barrier);
            case 'DIGITUNDER':
                return array_of_digits.filter(digit => +digit < +barrier);
            case 'DIGITMATCH':
                return array_of_digits.filter(digit => +digit === +barrier);
            case 'DIGITDIFF':
                return array_of_digits.filter(digit => +digit !== +barrier);
            case 'DIGITODD':
                return array_of_digits.filter(digit => +digit % 2 !== 0);
            case 'DIGITEVEN':
                return array_of_digits.filter(digit => +digit % 2 === 0);
            default:
                throw new Error('Cannot Determine Winning numbers.');
        }
    };

    const highlightWinningNumbers = (winning_numbers) => {
        winning_numbers.forEach(digit => {
            const element = el_container.querySelector(`.digit-${digit}`);
            element.classList.remove('digit-losing');
            element.classList.add('digit-winning');
        });
    };

    const observeResize = () => {
        window.onresize = () => {
            if (el_peek_box) {
                adjustBoxSizes();
                el_peek_box.setAttribute('style', `transform: translateX(${calculateOffset()}px)`);
            }
        };
    };

    // Calculate peek-box left offset.
    const calculateOffset = () => {
        const left_offset = document.querySelector(`.digit-${current_spot}`).offsetLeft;
        return left_offset - style_offset_correction;
    };

    const markAsLost = () => {
        if (!el_peek_box || !el_peek) {
            setElements();
        }
        el_peek.classList.remove('digit-winning', 'digit-running');
        el_peek_box.classList.remove('digit-winning', 'digit-running');
        el_peek.classList.add('digit-losing');
        el_peek_box.classList.add('digit-losing');
    };

    const markDigitAsWon = (digit) => {
        el_container.querySelector(`.digit-${digit}`).classList.add('digit-won');
    };

    const markDigitAsLost = (digit) => {
        el_container.querySelector(`.digit-${digit}`).classList.add('digit-lost');
    };

    const markAsWon = () => {
        if (!el_peek_box || !el_peek) {
            setElements();
        }
        el_peek_box.classList.remove('digit-losing', 'digit-running');
        el_peek_box.classList.add('digit-winning');
        el_peek.classList.remove('digit-losing', 'digit-running');
        el_peek.classList.add('digit-winning');
    };

    const setElements = () => {
        el_peek     = el_container.querySelector('.peek');
        el_peek_box = el_container.querySelector('.peek-box');
        el_mask     = el_peek_box.querySelector('.peek-box > .mask');
    };

    const update = (current_tick_count, { quote, epoch, barrier }) => {
        if (!isBarrierMissing(type, barrier) && is_lazy_numbers) {
            highlightWinningNumbers(getWinningNumbers(type, barrier));
            is_lazy_numbers = false;
        }
        setElements(epoch);
        el_container.classList.remove('invisible');
        adjustBoxSizes();
        current_spot = quote.substr(-1);

        el_mask.innerText = `${current_tick_count} / ${total_tick_count}`;

        el_peek_box.classList.add('digit-running');
        el_peek.classList.add('digit-running');

        el_peek_box.setAttribute('style', `transform: translateX(${calculateOffset()}px)`);
    };

    const remove = () => {
        window.onresize = null;
        while (el_container && el_container.firstChild) {
            el_container.removeChild(el_container.firstChild);
        }
        if (el_container) el_container.classList.add('invisible');
    };

    const countDecimals = (value) => {
        if (Math.floor(value) !== value) return value.toString().split('.')[1].length || 0;
        return 0;
    };

    const calculateDistance = (old_digit, new_digit) => Math.abs(old_digit - new_digit);

    const countUp = (start, end, duration, element, render) => {
        const decimal_points = countDecimals(start.replace('/,+/', ''));
        const f_start = parseFloat(start.replace(/,+/, ''));
        const range = calculateDistance(f_start, end);
        const step = Math.abs(range / 60);
        const increment = end > f_start ? (1 * step) : (-1 * step);
        let current = f_start;
        let i = 0;

        const renderTick = () => {
            i++;
            current += increment;

            element.innerHTML = render(current.toFixed(decimal_points));

            if (i <= 15) {
                requestAnimationFrame(renderTick);
            } else {
                current = end;
                element.innerHTML = render(current.toFixed(decimal_points));
            }
        };

        requestAnimationFrame(renderTick);
    };

    return {
        init,
        update,
        countUp,
        markAsWon,
        markAsLost,
        markDigitAsLost,
        markDigitAsWon,
        remove,
    };
})();

module.exports = DigitTicker;
<|endoftext|>


<commit_before>Accounts.onCreateUser(function(options, user) {
  //send user email
  sendWelcomeEmail(options.email, "no-reply@cherish.com", options.email);

  if(user.services.facebook) {
    options.profile.avatarImg = "http://graph.facebook.com/" + user.services.facebook.id + "/picture/?type=large";
  } else {
    options.profile.avatarImg = "/images/placeholder-avatar.jpg";
  }
  user.profile = options.profile ? options.profile : {};
  return user;
});<commit_msg>Remove sending of emails<commit_after>Accounts.onCreateUser(function(options, user) {
  if(user.services.facebook) {
    options.profile.avatarImg = "http://graph.facebook.com/" + user.services.facebook.id + "/picture/?type=large";
  } else {
    options.profile.avatarImg = "/images/placeholder-avatar.jpg";
  }
  user.profile = options.profile ? options.profile : {};
  return user;
});<|endoftext|>


<commit_before>"use strict";
const _ = require("lodash");
const statisticModel = require("./output/statistic.json");

function isEmptiness(judge) {
    return !judge.declarations || !_.size(judge.declarations);
}

/**
 * Returns a random integer between min (inclusive) and max (inclusive)
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function toSquereMeters(space, space_units) {
    if (space === "") {
        return 0;
    }
    space = parseFloat(space.replace(",", "."));

    if (space_units === "м²" || space_units === "") {
        return space;
    } else if (space_units === "га") {
        return space * 10000;
    } else if (space_units === "соток") {
        return space * 100;
    }
}

function toUAH(sum, currency) {
    if (sum === "") {
        return 0;
    }
    sum = parseFloat(sum.replace(",", "."));
    if (currency === "грн" || currency === "UAH" || currency === "") {
        return sum;
    } else if (currency === "OTHER") {

        // Карбованці
        return 0;
    } else if (currency === "USD") {
        return sum * 25;
    } else if (currency === "EUR") {
        return sum * 28;
    }
}

var getIndex = {
    income: function income(declaration) {
        return _.toSafeInteger(parseFloat(_.get(declaration, "income.5.value").replace(",", ".")));
    },
    familyIncome: function familyIncome(declaration) {
        const income = _.get(declaration, "income.5.family");
        if (income) {
            return _.toSafeInteger(parseFloat(income.replace(",", ".")));
        }

    },
    landArea: function landArea(declaration) {
        return _.reduce(_.get(declaration, "estate.23"), function (sum, land) {
            return sum + toSquereMeters(land.space, land.space_units);
        }, 0);
    },
    landAmount: function landAmount(declaration) {
        return _.size(_.get(declaration, "estate.23"));
    },
    houseArea: function houseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.24"), function (sum, house) {
            return sum + toSquereMeters(house.space, house.space_units);
        }, 0).toFixed(2);
    },
    houseAmount: function houseAmount(declaration) {
        return _.size(_.get(declaration, "estate.24"));
    },
    familyHouseArea: function familyHouseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.30"), function (sum, house) {
            return sum + toSquereMeters(house.space, house.space_units);
        }, 0).toFixed(2);
    },
    familyHouseAmount: function familyHouseAmount(declaration) {
        return _.size(_.get(declaration, "estate.30"));
    },
    flatArea: function houseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.25"), function (sum, flat) {
            return sum + toSquereMeters(flat.space, flat.space_units);
        }, 0).toFixed(2);
    },
    flatAmount: function houseAmount(declaration) {
        return _.size(_.get(declaration, "estate.25"));
    },
    carAmount: function carAmount(declaration) {
        return _.size(_.get(declaration, "vehicle.35"));
    },
    bankAccount: function bankAccount(declaration) {
        return _.reduce(_.get(declaration, "banks.45"), function (sum, bank) {
            return sum + toUAH(bank.sum, bank.sum_units);
        }, 0);
    }
};

module.exports = function analytics(judge) {
    if (isEmptiness(judge)) {
        return;
    }

    var result = [];

    judge.declarations.forEach((declaration) => {
        const year = _.toSafeInteger(_.get(declaration, "intro.declaration_year"));
        const findThisYear = {};
        findThisYear[statisticModel.year] = year;
        if (_.find(result, findThisYear)) {
            return;
        }

        let statistic = {};
        statistic[statisticModel.year] = year;
        statistic[statisticModel.income] = getIndex.income(declaration);
        statistic[statisticModel.familyIncome] = getIndex.familyIncome(declaration);
        statistic[statisticModel.landArea] = getIndex.landArea(declaration);
        statistic[statisticModel.landAmount] = getIndex.landAmount(declaration);
        statistic[statisticModel.houseArea] = getIndex.houseArea(declaration);
        statistic[statisticModel.houseAmount] = getIndex.houseAmount(declaration);
        statistic[statisticModel.familyHouseArea] = getIndex.familyHouseArea(declaration);
        statistic[statisticModel.familyHouseAmount] = getIndex.familyHouseAmount(declaration);
        statistic[statisticModel.flatArea] = getIndex.flatArea(declaration);
        statistic[statisticModel.flatAmount] = getIndex.flatAmount(declaration);
        statistic[statisticModel.carAmount] = getIndex.carAmount(declaration);

        if (2015 === year) {
            statistic[statisticModel.complaintAmount] = _.toSafeInteger(judge["Кількість справ"]);
            statistic[statisticModel.complainsAmount] = _.toSafeInteger(judge["Кількість скарг"]);
        }

        statistic[statisticModel.bankAccount] = getIndex.bankAccount(declaration);

        result.push(_.omitBy(statistic, (stat) => {
            return _.isUndefined(stat) || stat === 0;
        }));
    });

    return result;
};
//console.log(analytics({"Department":"Романівський районний суд Житомирської області","Region":"Житомирська область","Position":"Суддя Романівського районного суду Житомирської області","Name":"Бабич Сергій Васильович","Link":"https://drive.google.com/open?id=0BygiyWAl79DMQnBsVENuVXRTQVk","Note":"У меня","AdditionalNote":"","field8":"","Link 2015":"","field10":"","Кількість справ":"","Оскаржені":"","Кількість скарг":0,"Кількість дисциплінарних стягнень":"","Клейма":"","Фото":"","Як живе":"","key":"babich_sergiy_vasilovich","declarations":[{"vehicle":{"35":[{"brand_unclear":false,"brand":"Mitsubishi Pajero Sport","sum_rent":"","year":"2011","sum_comment":"","sum_rent_comment":"","brand_info_unclear":false,"brand_info":"2477 куб. см.","sum":""}]},"general":{"family_raw":"","post":{"region":"Житомирська область","post":"заступник голови романівського районного суду житомирської області","region_hidden":false,"office_unclear":false,"office":"Загальний місцевий суд","post_unclear":false,"region_unclear":false,"office_hidden":false},"patronymic":"Васильович","inn":"","full_name":"Бабич Сергій Васильович","inn_hidden":true,"inn_unclear":false,"full_name_suggest":{"output":"Бабич Сергій Васильович","input":["Бабич Сергій Васильович","Сергій Васильович Бабич","Сергій Бабич"]},"last_name":"Бабич","last_name_unclear":false,"family":[{"relations_hidden":false,"relations":"Подружжя","inn_hidden":true,"family_name":"Бабич О. С","relations_other":"","inn":"","name_hidden":false,"inn_unclear":false,"name_unclear":false,"relations_unclear":false},{"family_name":"Бабич О. С","relations":"Дитина","inn_hidden":true,"relations_other":"","inn":"","name_hidden":false,"inn_unclear":false,"name_unclear":false,"relations_unclear":false},{"family_name":"Бабич Ф. С","relations":"Дитина","inn_hidden":true,"relations_other":"","inn":"","inn_unclear":false,"name_unclear":true,"name_hidden":false}],"name":"Сергій","last_name_hidden":false,"patronymic_unclear":false,"addresses":[{"place_address_unclear":false,"place_unclear":false,"place_city":"Скраглівка","place_address_hidden":true,"place_city_type_unclear":false,"place":"Житомирська область","place_district":"Бердичівський","place_district_unclear":false,"place_city_hidden":false,"place_hidden":false,"place_city_type_hidden":false,"place_district_hidden":false,"place_city_type":"Село","place_city_unclear":true,"place_address":""}],"name_unclear":false,"name_hidden":false},"declaration":{"additional_info":"","notfull_lostpages":"","additional_info_text":"","date":"2015-03-17T00:00:00","notfull":"","url":"http://unshred.it/static/declarations/chosen_ones/mega_batch/babych_serhii_vasylovych.pdf"},"estate":{"23":[{"space_units_unclear":false,"address":"Бердичівський р-н, с. Велика П'ятигірка","space_hidden":false,"costs_hidden":false,"space_units":"м²","costs_comment":"","space":"2800","costs_rent_comment":"","region_hidden":false,"region":"Житомирська область","space_unclear":false,"address_hidden":false,"costs_rent_hidden":false,"space_comment":"","costs":"","space_units_hidden":false,"costs_rent":""}],"25":[{"space_comment_unclear":false,"address":"смт. Романів","costs_rent_comment_hidden":false,"space_hidden":false,"costs_hidden":false,"space_units":"м²","region_unclear":false,"address_unclear":true,"costs_rent_hidden":false,"space":"61.6","costs_rent_comment":"","costs_comment_hidden":false,"region_hidden":false,"region":"","space_unclear":true,"costs_comment":"","address_hidden":false,"space_comment":"","costs":"","space_units_hidden":false,"costs_rent":"4800"}],"27":[{"address_unclear":true,"address":"смт. Романів","costs_comment":"","costs_rent_comment_hidden":false,"costs_hidden":false,"space_units":"м²","costs_rent_hidden":false,"space":"20","costs_rent_comment":"","costs_comment_hidden":false,"region":"Житомирська область","space_unclear":false,"address_hidden":false,"region_hidden":false,"space_comment":"","costs":"","costs_rent":"1200"}]},"intro":{"isnotdeclaration":"","declaration_year_unclear":false,"declaration_year":"2014"},"source":"VULYK","banks":{"45":[{"sum_foreign_units":"UAH","sum_units":"UAH","sum_foreign_comment":"","sum_unclear":false,"sum_foreign_unclear":false,"sum_hidden":false,"sum_comment":"","sum_foreign":"","sum":"3100","sum_foreign_hidden":false,"sum_comment_hidden":false}],"46":[{"sum_foreign_units":"UAH","sum_units":"UAH","sum_comment_hidden":false,"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":"3100"}]},"id":"vulyk_63_129","liabilities":{"54":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"55":{"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"56":{"sum_foreign_comment":"","sum_comment":"","sum_unclear":true,"sum_foreign":"","sum":"5400"},"57":{"sum_foreign_comment":"","sum_comment_hidden":false,"sum_unclear":false,"sum_comment":"","sum_foreign":"","sum":""},"58":{"sum_comment":"","sum_foreign":"","sum_comment_hidden":false,"sum_foreign_comment":"","sum":""},"59":{"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"60":{"sum_comment_unclear":false,"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"61":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"62":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"63":{"sum_comment_hidden":false,"sum_unclear":false,"sum_comment":"","sum_foreign":"","sum_hidden":false,"sum_foreign_comment":"","sum":""},"64":{"sum_comment":"","sum_foreign":"","sum_comment_hidden":false,"sum_foreign_comment":"","sum":""}},"income":{"5":{"value":"372586","comment":"","value_unclear":false,"value_hidden":false,"family_unclear":false,"comment_hidden":false,"family":"46588","family_hidden":false,"family_comment":""},"6":{"value":"226123","comment":"","comment_unclear":false,"value_unclear":false,"family_unclear":false,"family":"46588","family_hidden":false,"family_comment":""},"7":{"value":"","comment":"","value_hidden":false,"source_name_unclear":false,"source_name":"","source_name_hidden":false,"family":"","family_comment":""},"8":{"value":"","comment":"","value_hidden":false,"family":"","family_hidden":false,"family_comment":""},"9":{"value":"463","comment":"","value_unclear":false,"value_hidden":false,"family_unclear":false,"family":"","family_hidden":false,"family_comment":""},"10":{"value":"","comment":"","family":"","family_comment":""},"11":{"value":"","comment":"","family":"","family_comment":""},"12":{"value":"","comment":"","family":"","family_comment":""},"13":{"value":"","comment":"","family":"","family_comment":""},"14":{"value":"","comment":"","family":"","family_comment":""},"15":{"value":"","comment":"","family":"","family_comment":""},"16":{"value":"146000","comment":"","value_unclear":false,"family_unclear":false,"family":"","family_comment":""},"17":{"value":"","comment":"","family":"","family_comment":""},"18":{"value":"","comment":"","family":"","family_comment":""},"19":{"value":"","comment":"","comment_unclear":false,"family":"","family_comment":""},"20":{"value":"","comment":"","comment_unclear":false,"value_unclear":false,"value_hidden":false,"family_unclear":false,"comment_hidden":false,"family_comment_unclear":false,"family":"","family_hidden":false,"family_comment":""}}}],"declarationsLength":1}))
<commit_msg>Scraper: omit 0.00 analytics data<commit_after>"use strict";
const _ = require("lodash");
const statisticModel = require("./output/statistic.json");

function isEmptiness(judge) {
    return !judge.declarations || !_.size(judge.declarations);
}

/**
 * Returns a random integer between min (inclusive) and max (inclusive)
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function toSquereMeters(space, space_units) {
    if (space === "") {
        return 0;
    }
    space = parseFloat(space.replace(",", "."));

    if (space_units === "м²" || space_units === "") {
        return space;
    } else if (space_units === "га") {
        return space * 10000;
    } else if (space_units === "соток") {
        return space * 100;
    }
}

function toUAH(sum, currency) {
    if (sum === "") {
        return 0;
    }
    sum = parseFloat(sum.replace(",", "."));
    if (currency === "грн" || currency === "UAH" || currency === "") {
        return sum;
    } else if (currency === "OTHER") {

        // Карбованці
        return 0;
    } else if (currency === "USD") {
        return sum * 25;
    } else if (currency === "EUR") {
        return sum * 28;
    }
}

var getIndex = {
    income: function income(declaration) {
        return _.toSafeInteger(parseFloat(_.get(declaration, "income.5.value").replace(",", ".")));
    },
    familyIncome: function familyIncome(declaration) {
        const income = _.get(declaration, "income.5.family");
        if (income) {
            return _.toSafeInteger(parseFloat(income.replace(",", ".")));
        }

    },
    landArea: function landArea(declaration) {
        return _.reduce(_.get(declaration, "estate.23"), function (sum, land) {
            return sum + toSquereMeters(land.space, land.space_units);
        }, 0);
    },
    landAmount: function landAmount(declaration) {
        return _.size(_.get(declaration, "estate.23"));
    },
    houseArea: function houseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.24"), function (sum, house) {
            return sum + toSquereMeters(house.space, house.space_units);
        }, 0).toFixed(2);
    },
    houseAmount: function houseAmount(declaration) {
        return _.size(_.get(declaration, "estate.24"));
    },
    familyHouseArea: function familyHouseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.30"), function (sum, house) {
            return sum + toSquereMeters(house.space, house.space_units);
        }, 0).toFixed(2);
    },
    familyHouseAmount: function familyHouseAmount(declaration) {
        return _.size(_.get(declaration, "estate.30"));
    },
    flatArea: function houseArea(declaration) {
        return _.reduce(_.get(declaration, "estate.25"), function (sum, flat) {
            return sum + toSquereMeters(flat.space, flat.space_units);
        }, 0).toFixed(2);
    },
    flatAmount: function houseAmount(declaration) {
        return _.size(_.get(declaration, "estate.25"));
    },
    carAmount: function carAmount(declaration) {
        return _.size(_.get(declaration, "vehicle.35"));
    },
    bankAccount: function bankAccount(declaration) {
        return _.reduce(_.get(declaration, "banks.45"), function (sum, bank) {
            return sum + toUAH(bank.sum, bank.sum_units);
        }, 0);
    }
};

module.exports = function analytics(judge) {
    if (isEmptiness(judge)) {
        return;
    }

    var result = [];

    judge.declarations.forEach((declaration) => {
        const year = _.toSafeInteger(_.get(declaration, "intro.declaration_year"));
        const findThisYear = {};
        findThisYear[statisticModel.year] = year;
        if (_.find(result, findThisYear)) {
            return;
        }

        let statistic = {};
        statistic[statisticModel.year] = year;
        statistic[statisticModel.income] = getIndex.income(declaration);
        statistic[statisticModel.familyIncome] = getIndex.familyIncome(declaration);
        statistic[statisticModel.landArea] = getIndex.landArea(declaration);
        statistic[statisticModel.landAmount] = getIndex.landAmount(declaration);
        statistic[statisticModel.houseArea] = getIndex.houseArea(declaration);
        statistic[statisticModel.houseAmount] = getIndex.houseAmount(declaration);
        statistic[statisticModel.familyHouseArea] = getIndex.familyHouseArea(declaration);
        statistic[statisticModel.familyHouseAmount] = getIndex.familyHouseAmount(declaration);
        statistic[statisticModel.flatArea] = getIndex.flatArea(declaration);
        statistic[statisticModel.flatAmount] = getIndex.flatAmount(declaration);
        statistic[statisticModel.carAmount] = getIndex.carAmount(declaration);

        if (2015 === year) {
            statistic[statisticModel.complaintAmount] = _.toSafeInteger(judge["Кількість справ"]);
            statistic[statisticModel.complainsAmount] = _.toSafeInteger(judge["Кількість скарг"]);
        }

        statistic[statisticModel.bankAccount] = getIndex.bankAccount(declaration);

        result.push(_.omitBy(statistic, (stat) => {
            return _.isUndefined(stat) || stat == 0;
        }));
    });

    return result;
};
//console.log(analytics({"Department":"Романівський районний суд Житомирської області","Region":"Житомирська область","Position":"Суддя Романівського районного суду Житомирської області","Name":"Бабич Сергій Васильович","Link":"https://drive.google.com/open?id=0BygiyWAl79DMQnBsVENuVXRTQVk","Note":"У меня","AdditionalNote":"","field8":"","Link 2015":"","field10":"","Кількість справ":"","Оскаржені":"","Кількість скарг":0,"Кількість дисциплінарних стягнень":"","Клейма":"","Фото":"","Як живе":"","key":"babich_sergiy_vasilovich","declarations":[{"vehicle":{"35":[{"brand_unclear":false,"brand":"Mitsubishi Pajero Sport","sum_rent":"","year":"2011","sum_comment":"","sum_rent_comment":"","brand_info_unclear":false,"brand_info":"2477 куб. см.","sum":""}]},"general":{"family_raw":"","post":{"region":"Житомирська область","post":"заступник голови романівського районного суду житомирської області","region_hidden":false,"office_unclear":false,"office":"Загальний місцевий суд","post_unclear":false,"region_unclear":false,"office_hidden":false},"patronymic":"Васильович","inn":"","full_name":"Бабич Сергій Васильович","inn_hidden":true,"inn_unclear":false,"full_name_suggest":{"output":"Бабич Сергій Васильович","input":["Бабич Сергій Васильович","Сергій Васильович Бабич","Сергій Бабич"]},"last_name":"Бабич","last_name_unclear":false,"family":[{"relations_hidden":false,"relations":"Подружжя","inn_hidden":true,"family_name":"Бабич О. С","relations_other":"","inn":"","name_hidden":false,"inn_unclear":false,"name_unclear":false,"relations_unclear":false},{"family_name":"Бабич О. С","relations":"Дитина","inn_hidden":true,"relations_other":"","inn":"","name_hidden":false,"inn_unclear":false,"name_unclear":false,"relations_unclear":false},{"family_name":"Бабич Ф. С","relations":"Дитина","inn_hidden":true,"relations_other":"","inn":"","inn_unclear":false,"name_unclear":true,"name_hidden":false}],"name":"Сергій","last_name_hidden":false,"patronymic_unclear":false,"addresses":[{"place_address_unclear":false,"place_unclear":false,"place_city":"Скраглівка","place_address_hidden":true,"place_city_type_unclear":false,"place":"Житомирська область","place_district":"Бердичівський","place_district_unclear":false,"place_city_hidden":false,"place_hidden":false,"place_city_type_hidden":false,"place_district_hidden":false,"place_city_type":"Село","place_city_unclear":true,"place_address":""}],"name_unclear":false,"name_hidden":false},"declaration":{"additional_info":"","notfull_lostpages":"","additional_info_text":"","date":"2015-03-17T00:00:00","notfull":"","url":"http://unshred.it/static/declarations/chosen_ones/mega_batch/babych_serhii_vasylovych.pdf"},"estate":{"23":[{"space_units_unclear":false,"address":"Бердичівський р-н, с. Велика П'ятигірка","space_hidden":false,"costs_hidden":false,"space_units":"м²","costs_comment":"","space":"2800","costs_rent_comment":"","region_hidden":false,"region":"Житомирська область","space_unclear":false,"address_hidden":false,"costs_rent_hidden":false,"space_comment":"","costs":"","space_units_hidden":false,"costs_rent":""}],"25":[{"space_comment_unclear":false,"address":"смт. Романів","costs_rent_comment_hidden":false,"space_hidden":false,"costs_hidden":false,"space_units":"м²","region_unclear":false,"address_unclear":true,"costs_rent_hidden":false,"space":"61.6","costs_rent_comment":"","costs_comment_hidden":false,"region_hidden":false,"region":"","space_unclear":true,"costs_comment":"","address_hidden":false,"space_comment":"","costs":"","space_units_hidden":false,"costs_rent":"4800"}],"27":[{"address_unclear":true,"address":"смт. Романів","costs_comment":"","costs_rent_comment_hidden":false,"costs_hidden":false,"space_units":"м²","costs_rent_hidden":false,"space":"20","costs_rent_comment":"","costs_comment_hidden":false,"region":"Житомирська область","space_unclear":false,"address_hidden":false,"region_hidden":false,"space_comment":"","costs":"","costs_rent":"1200"}]},"intro":{"isnotdeclaration":"","declaration_year_unclear":false,"declaration_year":"2014"},"source":"VULYK","banks":{"45":[{"sum_foreign_units":"UAH","sum_units":"UAH","sum_foreign_comment":"","sum_unclear":false,"sum_foreign_unclear":false,"sum_hidden":false,"sum_comment":"","sum_foreign":"","sum":"3100","sum_foreign_hidden":false,"sum_comment_hidden":false}],"46":[{"sum_foreign_units":"UAH","sum_units":"UAH","sum_comment_hidden":false,"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":"3100"}]},"id":"vulyk_63_129","liabilities":{"54":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"55":{"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"56":{"sum_foreign_comment":"","sum_comment":"","sum_unclear":true,"sum_foreign":"","sum":"5400"},"57":{"sum_foreign_comment":"","sum_comment_hidden":false,"sum_unclear":false,"sum_comment":"","sum_foreign":"","sum":""},"58":{"sum_comment":"","sum_foreign":"","sum_comment_hidden":false,"sum_foreign_comment":"","sum":""},"59":{"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"60":{"sum_comment_unclear":false,"sum_comment":"","sum_foreign":"","sum_foreign_comment":"","sum":""},"61":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"62":{"sum_comment":"","sum_foreign":"","sum_unclear":false,"sum_foreign_comment":"","sum":""},"63":{"sum_comment_hidden":false,"sum_unclear":false,"sum_comment":"","sum_foreign":"","sum_hidden":false,"sum_foreign_comment":"","sum":""},"64":{"sum_comment":"","sum_foreign":"","sum_comment_hidden":false,"sum_foreign_comment":"","sum":""}},"income":{"5":{"value":"372586","comment":"","value_unclear":false,"value_hidden":false,"family_unclear":false,"comment_hidden":false,"family":"46588","family_hidden":false,"family_comment":""},"6":{"value":"226123","comment":"","comment_unclear":false,"value_unclear":false,"family_unclear":false,"family":"46588","family_hidden":false,"family_comment":""},"7":{"value":"","comment":"","value_hidden":false,"source_name_unclear":false,"source_name":"","source_name_hidden":false,"family":"","family_comment":""},"8":{"value":"","comment":"","value_hidden":false,"family":"","family_hidden":false,"family_comment":""},"9":{"value":"463","comment":"","value_unclear":false,"value_hidden":false,"family_unclear":false,"family":"","family_hidden":false,"family_comment":""},"10":{"value":"","comment":"","family":"","family_comment":""},"11":{"value":"","comment":"","family":"","family_comment":""},"12":{"value":"","comment":"","family":"","family_comment":""},"13":{"value":"","comment":"","family":"","family_comment":""},"14":{"value":"","comment":"","family":"","family_comment":""},"15":{"value":"","comment":"","family":"","family_comment":""},"16":{"value":"146000","comment":"","value_unclear":false,"family_unclear":false,"family":"","family_comment":""},"17":{"value":"","comment":"","family":"","family_comment":""},"18":{"value":"","comment":"","family":"","family_comment":""},"19":{"value":"","comment":"","comment_unclear":false,"family":"","family_comment":""},"20":{"value":"","comment":"","comment_unclear":false,"value_unclear":false,"value_hidden":false,"family_unclear":false,"comment_hidden":false,"family_comment_unclear":false,"family":"","family_hidden":false,"family_comment":""}}}],"declarationsLength":1}))
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Service.extend({
  /**
  * The base Howler Object: Allows you to change global settings
  * https://github.com/goldfire/howler.js/tree/2.0#global-core-methods
  **/
  Howler,

  /**
   * The base Howl object: Has no use to the consuming app, exists here for testing purposes
   */
  Howl,

  /**
  * Array of strings (names of sounds) that acts as a registry for sound instances
  **/
  sounds: Ember.A(),

  /**
  * Instantiate a "sound" and place on this service by name
  *
  * @param {string}           name  The name that you will use to refer to the sound
  * @param {array || string}  src   path, as a string, or an array of strings, to the sound's mp3 file(s). Can be URLs or base64 data URIs. https://github.com/goldfire/howler.js/tree/2.0#src-array--required
  * @param {object}           opts  An optional POJO that accepts Howler options https://github.com/goldfire/howler.js/tree/2.0#more-playback-options
  * @return {object}                A Howler "Howl" object instance
  **/
  load(name, src, opts={}) {
    const Howl = this.get('Howl');

    if (Ember.isArray(src)) {
      opts.src = src;
    } else {
      opts.src = [src];
    }

    this.set(name, new Howl(opts));
    this.get('sounds').pushObject(name);
    return this.get(name);
  },

  /**
   * unload - Removes a sound from this service by "name" and unloads it from Howler
   *
   * @param  {string} name The name of the sound you would like to unload
   */
  unload(name) {
    this.get(name).unload();
    this.set(name, null);
    this.get('sounds').removeObject(name);
  },

  /**
   * pan - Pans a sound left or right
   *
   * @param  {type} name  The name of the sound you would like to pan
   * @param  {int} value  The direction and amount between -1 (hard left) and 1 (hard right)
   * @return {object}     The Howler "Howl" object instance
   */
  pan(name, value) {
    this.get(name).pos(value);
    return this.get(name);
  }
});
<commit_msg>Needs cleanup, but currently working with sound fonts<commit_after>import Ember from 'ember';

export default Ember.Service.extend({
  /**
  * The base Howler Object: Allows you to change global settings
  * https://github.com/goldfire/howler.js/tree/2.0#global-core-methods
  **/
  Howler,

  /**
   * The base Howl object: Has no use to the consuming app, exists here for testing purposes
   */
  Howl,

  /**
  * Array of strings (names of sounds) that acts as a registry for sound instances
  **/
  sounds: Ember.A(),

  context: new AudioContext(),

  /**
  * Instantiate a "sound" and place on this service by name
  *
  * @param {string}           name  The name that you will use to refer to the sound
  * @param {array || string}  src   path, as a string, or an array of strings, to the sound's mp3 file(s). Can be URLs or base64 data URIs. https://github.com/goldfire/howler.js/tree/2.0#src-array--required
  * @param {object}           opts  An optional POJO that accepts Howler options https://github.com/goldfire/howler.js/tree/2.0#more-playback-options
  * @return {object}                A Howler "Howl" object instance
  **/
  load(name, src, opts={}) {
    const ctx = this.get('context');
    return fetch(`http://localhost:4200/${src}`)
      .then((response) => response.arrayBuffer())
      .then((response) => ctx.decodeAudioData(response))
      .then((decodedAudio) => {
        this.set(name, decodedAudio);
        this.get('sounds').pushObject(name);
      });
  },

  loadSoundFont(name, src) {
    const ctx = this.get('context');

    this.set(name, Ember.Object.create());

    return fetch(`http://localhost:4200/${src}`)
      .then((response) => response.text())
      .then((text) => {
        // Strip out all the unnecessary stuff
        const array = text
          .replace(new RegExp('data:audio/mpeg;base64,', 'g'), '')
          .replace(new RegExp(':', 'g'), '')
          .replace(new RegExp('"', 'g'), '')
          .split('\n')
          .slice(3);

        // remove the trailing "}"
        array.pop();

        return array;
      })
      .then((data) => {
        const promises = data.map((item) => {
          // Note names and values are separated with a space
          const note = item.split(' ');
          const noteName = note[0];

          // Transform base64 note value to Uint8Array
          const noteValue = this.base64DecodeToArray(note[1]);

          // Get web audio api audio data from array buffer, include note name
          return ctx.decodeAudioData(noteValue.buffer)
            .then((buffer) => [noteName, buffer]);
        });

        // Wait for array of promises to resolve before continuing
        return Ember.RSVP.all(promises);
      })
      .then((audio) => {
        // Set audio data on previously created Ember.Object called ${name}
        audio.map((note) => this.set(`${name}.${note[0]}`, note[1]));
      });
  },

  play(name, note) {
    const ctx = this.get('context');
    const panner = this.get(`${name}Panner`);
    const node = ctx.createBufferSource();
    let decodedAudio;

    if (note) {
      decodedAudio = this.get(`${name}.${note}`);
    } else {
      decodedAudio = this.get(name);
    }

    if (panner) {
      node.connect(panner);
      panner.connect(ctx.destination);
    } else {
      node.connect(ctx.destination);
    }

    node.buffer = decodedAudio;
    node.start();
  },

  /**
   * unload - Removes a sound from this service by "name" and unloads it from Howler
   *
   * @param  {string} name The name of the sound you would like to unload
   */
  unload(name) {
    this.get(name).unload();
    this.set(name, null);
    this.get('sounds').removeObject(name);
  },

  /**
   * pan - Pans a sound left or right
   *
   * @param  {type} name  The name of the sound you would like to pan
   * @param  {int} value  The direction and amount between -1 (hard left) and 1 (hard right)
   * @return {object}     The Howler "Howl" object instance
   */
  pan(name, value) {
    const panner = this.get('context').createStereoPanner();
    panner.pan.value = value;

    this.set(`${name}Panner`, panner);
  },

  base64DecodeToArray(sBase64, nBlocksSize) {
    var sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, "");
    var nInLen = sB64Enc.length;
    var nOutLen = nBlocksSize ?
      Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize :
      nInLen * 3 + 1 >> 2;
    var taBytes = new Uint8Array(nOutLen);

    for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
      nMod4 = nInIdx & 3;
      nUint24 |= this.b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
      if (nMod4 === 3 || nInLen - nInIdx === 1) {
        for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
          taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
        }
        nUint24 = 0;
      }
    }

    return taBytes;
  },

  b64ToUint6 (nChr) {
  return nChr > 64 && nChr < 91 ?
      nChr - 65
    : nChr > 96 && nChr < 123 ?
      nChr - 71
    : nChr > 47 && nChr < 58 ?
      nChr + 4
    : nChr === 43 ?
      62
    : nChr === 47 ?
      63
    :
      0;

}
});
<|endoftext|>


<commit_before>/**
 * FileInput.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:true, scripturl:true, browser:true */
/*global define:true */

/**
@class moxie/runtime/html5/file/FileInput
@private
*/
define("moxie/runtime/html5/file/FileInput", [
	"moxie/runtime/html5/Runtime",
	"moxie/core/utils/Basic",
	"moxie/core/utils/Dom",
	"moxie/core/utils/Events",
	"moxie/core/utils/Mime"
], function(extensions, Basic, Dom, Events, Mime) {

	function FileInput() {
		var _files = [], _options;

		Basic.extend(this, {
			init: function(options) {
				var comp = this, I = comp.getRuntime(), input, shimContainer, mimes;

				_options = options;
				_files = [];

				// figure out accept string
				mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept);

				shimContainer = I.getShimContainer();

				shimContainer.innerHTML = '<input id="' + I.uid +'" type="file" style="font-size:999px;opacity:0;"' +
					(_options.multiple && I.can('select_multiple') ? 'multiple webkitdirectory' : '') +
					' accept="' + mimes.join(',') + '" />';

				input = Dom.get(I.uid);

				// prepare file input to be placed underneath the browse_button element
				Basic.extend(input.style, {
					position: 'absolute',
					top: 0,
					left: 0,
					width: '100%',
					height: '100%'
				});

				(function() {
					var browseButton, zIndex, top;

					browseButton = Dom.get(_options.browse_button);

					// Route click event to the input[type=file] element for browsers that support such behavior
					if (I.can('summon_file_dialog')) {
						if (Dom.getStyle(browseButton, 'position') === 'static') {
							browseButton.style.position = 'relative';
						}

						zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;

						browseButton.style.zIndex = zIndex;
						shimContainer.style.zIndex = zIndex - 1;

						Events.addEvent(browseButton, 'click', function(e) {
							if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
								input.click();
							}
							e.preventDefault();
						}, comp.uid);
					}

					/* Since we have to place input[type=file] on top of the browse_button for some browsers,
					browse_button loses interactivity, so we restore it here */
					top = I.can('summon_file_dialog') ? browseButton : shimContainer;

					Events.addEvent(top, 'mouseover', function() {
						comp.trigger('mouseenter');
					}, comp.uid);

					Events.addEvent(top, 'mouseout', function() {
						comp.trigger('mouseleave');
					}, comp.uid);

					Events.addEvent(top, 'mousedown', function() {
						comp.trigger('mousedown');
					}, comp.uid);

					Events.addEvent(Dom.get(_options.container), 'mouseup', function() {
						comp.trigger('mouseup');
					}, comp.uid);

				}());

				input.onchange = function() { // there should be only one handler for this
					_files = [];

					if (_options.multiple) {
						// folders are represented by dots, filter them out (Chrome 21+)
						Basic.each(this.files, function(file) {
							if (file.name !== ".") { // if it doesn't looks like a folder
								_files.push(file);
							}
						});
					} else {
						_files = [].slice.call(this.files);
					}

					// Clearing the value enables the user to select the same file again if they want to
					this.value = '';
					comp.trigger('change');
				};
			},

			getFiles: function() {
				return _files;
			},

			disable: function(state) {
				var I = this.getRuntime(), input;

				if ((input = Dom.get(I.uid))) {
					input.disabled = !!state;
				}
			},

			destroy: function() {
				var I = this.getRuntime(), shimContainer = I.getShimContainer();

				Events.removeAllEvents(shimContainer, this.uid);
				Events.removeAllEvents(Dom.get(_options.container), this.uid);
				Events.removeAllEvents(Dom.get(_options.browse_button), this.uid);

				shimContainer.innerHTML = '';

				_files = _options = null;
			}
		});
	}

	return (extensions.FileInput = FileInput);
});<commit_msg>FileInput, HTML5: Turns out file input identified by (webkit)directory cannot select files at the same time and vice-versa (wtf?).<commit_after>/**
 * FileInput.js
 *
 * Copyright 2013, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:true, scripturl:true, browser:true */
/*global define:true */

/**
@class moxie/runtime/html5/file/FileInput
@private
*/
define("moxie/runtime/html5/file/FileInput", [
	"moxie/runtime/html5/Runtime",
	"moxie/core/utils/Basic",
	"moxie/core/utils/Dom",
	"moxie/core/utils/Events",
	"moxie/core/utils/Mime"
], function(extensions, Basic, Dom, Events, Mime) {

	function FileInput() {
		var _files = [], _options;

		Basic.extend(this, {
			init: function(options) {
				var comp = this, I = comp.getRuntime(), input, shimContainer, mimes;

				_options = options;
				_files = [];

				// figure out accept string
				mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept);

				shimContainer = I.getShimContainer();

				shimContainer.innerHTML = '<input id="' + I.uid +'" type="file" style="font-size:999px;opacity:0;"' +
					(_options.multiple && I.can('select_multiple') ? 'multiple' : '') +
					(_options.directory && I.can('select_multiple') ? 'webkitdirectory directory' : '') + // Chrome 21+
					' accept="' + mimes.join(',') + '" />';

				input = Dom.get(I.uid);

				// prepare file input to be placed underneath the browse_button element
				Basic.extend(input.style, {
					position: 'absolute',
					top: 0,
					left: 0,
					width: '100%',
					height: '100%'
				});

				(function() {
					var browseButton, zIndex, top;

					browseButton = Dom.get(_options.browse_button);

					// Route click event to the input[type=file] element for browsers that support such behavior
					if (I.can('summon_file_dialog')) {
						if (Dom.getStyle(browseButton, 'position') === 'static') {
							browseButton.style.position = 'relative';
						}

						zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;

						browseButton.style.zIndex = zIndex;
						shimContainer.style.zIndex = zIndex - 1;

						Events.addEvent(browseButton, 'click', function(e) {
							if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
								input.click();
							}
							e.preventDefault();
						}, comp.uid);
					}

					/* Since we have to place input[type=file] on top of the browse_button for some browsers,
					browse_button loses interactivity, so we restore it here */
					top = I.can('summon_file_dialog') ? browseButton : shimContainer;

					Events.addEvent(top, 'mouseover', function() {
						comp.trigger('mouseenter');
					}, comp.uid);

					Events.addEvent(top, 'mouseout', function() {
						comp.trigger('mouseleave');
					}, comp.uid);

					Events.addEvent(top, 'mousedown', function() {
						comp.trigger('mousedown');
					}, comp.uid);

					Events.addEvent(Dom.get(_options.container), 'mouseup', function() {
						comp.trigger('mouseup');
					}, comp.uid);

				}());

				input.onchange = function() { // there should be only one handler for this
					_files = [];

					if (_options.directory) {
						// folders are represented by dots, filter them out (Chrome 21+)
						Basic.each(this.files, function(file) {
							if (file.name !== ".") { // if it doesn't looks like a folder
								_files.push(file);
							}
						});
					} else {
						_files = [].slice.call(this.files);
					}

					// Clearing the value enables the user to select the same file again if they want to
					this.value = '';
					comp.trigger('change');
				};
			},

			getFiles: function() {
				return _files;
			},

			disable: function(state) {
				var I = this.getRuntime(), input;

				if ((input = Dom.get(I.uid))) {
					input.disabled = !!state;
				}
			},

			destroy: function() {
				var I = this.getRuntime(), shimContainer = I.getShimContainer();

				Events.removeAllEvents(shimContainer, this.uid);
				Events.removeAllEvents(Dom.get(_options.container), this.uid);
				Events.removeAllEvents(Dom.get(_options.browse_button), this.uid);

				shimContainer.innerHTML = '';

				_files = _options = null;
			}
		});
	}

	return (extensions.FileInput = FileInput);
});<|endoftext|>


<commit_before>var utils = require('./utils.js');
var c = utils.loadConfig();
var messenger = require('./messenger.js');
var factory = require('./factory.js');

//Room settings
var roomList = {},
	maxPlayersInRoom = c.maxPlayersInRoom,
	roomKickTimeout = c.roomKickTimeout;

exports.findARoom = function(clientID){
	if(getRoomCount() == 0){
		console.log("No rooms existing starting a new room");
		return generateNewRoom();
	}
	for(var sig2 in roomList){
		if(roomList[sig2].hasSpace()){
			return sig2;
		}
	}
	return generateNewRoom();
}

exports.joinARoom = function(sig,clientID){
	roomList[sig].join(clientID);
	return roomList[sig];
}

exports.kickFromRoom = function(clientID){
	var room = searchForRoom(clientID);
	if(room != undefined){
		room.leave(clientID);
	}
}

exports.getRoomBySig = function(sig){
	return roomList[sig];
}

exports.getRoomCount = function(){
	return getRoomCount();
}

exports.updateRooms = function(dt){
	for(var sig in roomList){
		var room = roomList[sig];
		if(!room.game.gameEnded){
			room.update(dt);
		} else if(room.alive){
			room.alive = false;
			messenger.messageRoomBySig(room.sig,"gameOver",room.game.winner);
			setTimeout(reclaimRoom,roomKickTimeout*1000,room.sig);
		}
	}
}

function getRoomCount(){
	var count = 0;
	for(var sig in roomList){
		count++;
	}
	return count;
}

function searchForRoom(id){
	var room;
	for(var sig in roomList){
		if(roomList[sig].checkRoom(id)){
			room = roomList[sig];
		}
	}
	return room;
}

function generateRoomSig(){
	var sig = utils.getRandomInt(0,99);
	if(roomList[sig] == null || roomList[sig] == undefined){
		return sig;
	}
	sig = generateRoomSig();
}

function reclaimRoom(sig){
	var room = roomList[sig];
	if(room == null){
		return;
	}
	for(var clientID in room.clientList){
		room.leave(clientID);
	}
	if(room.clientCount == 0){
		console.log("Reclaming old room " + sig);
		delete roomList[sig];
		roomList[sig] = undefined;
	}
}

function generateNewRoom(){
	var sig = generateRoomSig();
	roomList[sig] = factory.getRoom(sig,maxPlayersInRoom);
	return sig;
}
<commit_msg>fixed some potential cleanup issues<commit_after>var utils = require('./utils.js');
var c = utils.loadConfig();
var messenger = require('./messenger.js');
var factory = require('./factory.js');

//Room settings
var roomList = {},
	maxPlayersInRoom = c.maxPlayersInRoom,
	roomKickTimeout = c.roomKickTimeout;

exports.findARoom = function(clientID){
	if(getRoomCount() == 0){
		console.log("No rooms existing starting a new room");
		return generateNewRoom();
	}
	for(var sig2 in roomList){
		if(roomList[sig2].hasSpace()){
			return sig2;
		}
	}
	return generateNewRoom();
}

exports.joinARoom = function(sig,clientID){
	roomList[sig].join(clientID);
	return roomList[sig];
}

exports.kickFromRoom = function(clientID){
	var room = searchForRoom(clientID);
	if(room != undefined){
		room.leave(clientID);
	}
}

exports.getRoomBySig = function(sig){
	return roomList[sig];
}

exports.getRoomCount = function(){
	return getRoomCount();
}

exports.updateRooms = function(dt){
	for(var sig in roomList){
		var room = roomList[sig];
		if(room == null){
			delete roomList[sig];
			continue;
		}
		if(!room.game.gameEnded){
			room.update(dt);
		} else if(room.alive){
			room.alive = false;
			messenger.messageRoomBySig(room.sig,"gameOver",room.game.winner);
			reclaimRoom(room.sig); //setTimeout(reclaimRoom,roomKickTimeout*1000,room.sig);
		}
	}
}

function getRoomCount(){
	var count = 0;
	for(var sig in roomList){
		count++;
	}
	return count;
}

function searchForRoom(id){
	var room;
	for(var sig in roomList){
		if(roomList[sig].checkRoom(id)){
			room = roomList[sig];
		}
	}
	return room;
}

function generateRoomSig(){
	var sig = utils.getRandomInt(0,99);
	if(roomList[sig] == null || roomList[sig] == undefined){
		return sig;
	}
	sig = generateRoomSig();
}

function reclaimRoom(sig){
	var room = roomList[sig];
	if(room == null){
		return;
	}
	for(var clientID in room.clientList){
		room.leave(clientID);
	}
	if(room.clientCount == 0){
		console.log("Reclaming old room " + sig);
		roomList[sig] = null;
	}
}

function generateNewRoom(){
	var sig = generateRoomSig();
	roomList[sig] = factory.getRoom(sig,maxPlayersInRoom);
	return sig;
}
<|endoftext|>