<commit_before>/* ============================================================================

 >4SESz.,     _,     ,gSEE2zx.,_        .azx                    ,w.
@Sh. "QEE3.  JEE3.  &ss  `*4EEEEE2x.,_  "EEV  ,aS5^;dEEEE2x.,   VEEF  _
\E2`_,gF4EEEx.?jF   EE5L       `*4EEEEE2zpn..ZEEF ;sz.  `*EEESzw.w* '|EE.
  ,dEEF   `"?j]  _,_   ,_  _,     _,.     L.EEEF  !EEF  _,,  `"``    EE7   ,,_
 :EEE7 ,ws,`|EEL`JEEL`JEE)`JEEL zE5` E3. / [EE3  ,w.  zE2` Ek .zE5^JZE3.,6EF [3
 {EEE. VEE7.EE2  AE3. EEV  ZEEL{EEL ws. ;  [EE1  EEEt{E3. JEELEE3. JE5LJEEF ,w,
  \EEk,,>^ JEEL,@EEF ZE5L,ZE5^ "Q3. V2`.    \EEk,,J' "Q[ yE2^ VE[_zEE[,"QEL V5F
          ,ss  :EE7 ;EEF               L,szzw..            ,.,            ``
          \E5.,E5F  EE1.              /; ``*4EEEZhw._      EEEL
            ````     ``              JEEE.     `"45EEEhw.,,,]

From 2010 till ∞
typecode-js v 0.1
*/

// This module uses jQuery Hashchange (http://benalman.com/projects/jquery-hashchange-plugin/)
// as a fallback to emulate pushstate behavior on browsers that don't support pushstate.
// The hashchange plugin subsequently requires jQuery Migrate (https://github.com/jquery/jquery-migrate)
// if being used with jQuery version 1.9 +

define(['jquery', 'NIseed'], function($) {

    var window = this,
    NI = window.NI;

    function PushstateHelper(options) {

        var self = this, o, internal, fn, handlers;

        o = $.extend({
            app: null,
            use_hash: false
        }, options);

        internal = {
            name: 'mod.PushstateHelper',
            initial_state: false,
            previous_path: o.use_hash ?
                window.location.hash.replace('#', '') : window.location.pathname
        };
        internal.initial_state = internal.previous_path;

        fn = {
            init: function() {
                $(document).on('click', '.js-use-pushstate, .js-simulate-pushstate, .js-do-popstate', handlers.doc_click);

                $(window)
                    .on('popstate', handlers.popstate)
                    .on('pushstate', handlers.pushstate)
                    .on('simulate-pushstate', handlers.simulate_pushstate);

                if (o.use_hash) {
                    require(['jquery_migrate', 'hashchange'], function() {
                        $(window).on('hashchange', handlers.hashchange);
                        fn.statechange(window.location.hash);
                    });
                } else {
                    fn.statechange(window.location.pathname);
                }
            },
            statechange: function(pathname, data){
                var i, path_components, position, _event_data;

                if (o.use_hash) {
                    pathname = pathname.replace('#', '');
                }

                path_components = PushstateHelper.get_path_components(pathname);

                _event_data = {
                    path: pathname,
                    components: path_components,
                    data: data ? data : {}
                };

                _event_data.data.previous_path = internal.previous_path;

                o.app.events.trigger('navigationEvent:Pushstate', _event_data);

                internal.previous_path = _event_data.path;
            },

            get_path_components: function(){
                return internal.components;
            }
        };

        handlers = {
            doc_click: function(e, d) {
                var $t, _href, _data;
                e.preventDefault();
                $t = $(this);
                _href = $t.attr('HREF');
                _data = $t.data();
                if($t.hasClass('js-use-pushstate')){
                    e.stopImmediatePropagation();
                    if(o.use_hash){
                        window.location.hash = _href;
                    } else {
                        history.pushState(null, null, _href);
                    }
                    fn.statechange(_href, _data);
                } else if($t.hasClass('js-simulate-pushstate')) {
                    e.stopImmediatePropagation();
                    fn.statechange(_href, _data);
                } else if($t.hasClass('js-do-popstate')) {
                    e.stopImmediatePropagation();
                    history.back();
                }
            },
            popstate: function(e, d) {
                var pathname, cur;
                if(o.use_hash){
                    pathname = window.location.hash;
                    cur = pathname.replace('#', '');
                } else {
                    cur = pathname = window.location.pathname;
                }
                if (internal.previous_path == cur && internal.initial_state == cur) {
                    internal.initial_state = false;
                    return;
                }
                fn.statechange(pathname, d);
            },
            pushstate: function(e, d) {
                if(o.use_hash){
                    if(window.location.hash != d.pathname){
                        window.location.hash = d.pathname;
                    }
                } else {
                    if(window.location.pathname != d.pathname){
                        history.pushState(null, null, d.pathname);
                    }
                }
                if(!d || !d.prevent_propagation){
                    fn.statechange(d.pathname, d);
                }
            },
            simulate_pushstate: function(e, d) {
                if(!d || !d.prevent_propagation){
                    fn.statechange(d.pathname, d);
                }
            },
            hashchange: function(e, d) {
                if (!d || !d.prevent_propagation) {
                    fn.statechange(window.location.hash);
                }
            }
        };

        this.get_path_components = fn.get_path_components;

        fn.init();
        console.log(internal);
    }

    PushstateHelper.get_path_components = function(path){
        var components, position;
        if(path){
            components = path.split('/');
            position = components.length;
            while(position--){
                if(!components[position].length){
                    components.splice(position,1);
                }
            }
            return components;
        }
    };

    PushstateHelper.get_get_params = function() {
        var d, get_str, get_components;
        d = {};
        get_str = window.location.search;
        if (!get_str || !get_str.length) {
            return d;
        }
        // first character is always '?'
        get_str = get_str.substring(1);
        get_components = get_str.split('&');
        $.each(get_components, function(i, component) {
            var pair;
            pair = component.split('=');
            if (pair.length) {
                d[pair[0]] = pair[1] ? pair[1] : null;
            }
        });
        return d;
    };

    NI.PushstateHelper = PushstateHelper;

    return PushstateHelper;

});<commit_msg>updated Pushstate helper<commit_after>/* ============================================================================

 >4SESz.,     _,     ,gSEE2zx.,_        .azx                    ,w.
@Sh. "QEE3.  JEE3.  &ss  `*4EEEEE2x.,_  "EEV  ,aS5^;dEEEE2x.,   VEEF  _
\E2`_,gF4EEEx.?jF   EE5L       `*4EEEEE2zpn..ZEEF ;sz.  `*EEESzw.w* '|EE.
  ,dEEF   `"?j]  _,_   ,_  _,     _,.     L.EEEF  !EEF  _,,  `"``    EE7   ,,_
 :EEE7 ,ws,`|EEL`JEEL`JEE)`JEEL zE5` E3. / [EE3  ,w.  zE2` Ek .zE5^JZE3.,6EF [3
 {EEE. VEE7.EE2  AE3. EEV  ZEEL{EEL ws. ;  [EE1  EEEt{E3. JEELEE3. JE5LJEEF ,w,
  \EEk,,>^ JEEL,@EEF ZE5L,ZE5^ "Q3. V2`.    \EEk,,J' "Q[ yE2^ VE[_zEE[,"QEL V5F
          ,ss  :EE7 ;EEF               L,szzw..            ,.,            ``
          \E5.,E5F  EE1.              /; ``*4EEEZhw._      EEEL
            ````     ``              JEEE.     `"45EEEhw.,,,]

From 2010 till ∞
typecode-js v 0.1
*/

// This module uses jQuery Hashchange (http://benalman.com/projects/jquery-hashchange-plugin/)
// as a fallback to emulate pushstate behavior on browsers that don't support pushstate.
// The hashchange plugin subsequently requires jQuery Migrate (https://github.com/jquery/jquery-migrate)
// if being used with jQuery version 1.9 +

define(['jquery', 'NIseed'], function($) {

    var window = this,
    NI = window.NI;

    function PushstateHelper(options) {

        var self = this, o, internal, fn, handlers;

        o = $.extend({
            app: null,
            use_hash: false
        }, options);

        internal = {
            name: 'mod.PushstateHelper',
            initial_state: false,
            previous_path: o.use_hash ?
                window.location.hash.replace('#', '') : window.location.pathname
        };
        internal.initial_state = internal.previous_path;

        fn = {
            init: function() {
                $(document).on('click', '.js-use-pushstate, .js-simulate-pushstate, .js-do-popstate', handlers.doc_click);

                $(window)
                    .on('popstate', handlers.popstate)
                    .on('pushstate', handlers.pushstate)
                    .on('simulate-pushstate', handlers.simulate_pushstate);

                if (o.use_hash) {
                    require(['jquery_migrate', 'hashchange'], function() {
                        $(window).on('hashchange', handlers.hashchange);
                        fn.statechange(window.location.hash);
                    });
                } else {
                    fn.statechange(window.location.pathname);
                }
            },
            statechange: function(pathname, data){
                var i, path_components, position, _event_data;

                if (o.use_hash) {
                    pathname = pathname.replace('#', '');
                }

                path_components = PushstateHelper.get_path_components(pathname);

                _event_data = {
                    path: pathname,
                    components: path_components,
                    data: data ? data : {}
                };

                _event_data.data.previous_path = internal.previous_path;

                o.app.events.trigger('navigationEvent:Pushstate', _event_data);

                internal.previous_path = _event_data.path;
            },

            get_path_components: function(){
                return internal.components;
            }
        };

        handlers = {
            doc_click: function(e, d) {
                var $t, _href, _data;
                $t = $(this);
                if (!$t.hasClass('js-ignore-prevent-default')){
                    e.preventDefault();
                }
                _href = $t.attr('HREF');
                _data = $t.data();
                if($t.hasClass('js-use-pushstate')){
                    e.stopImmediatePropagation();
                    if(o.use_hash){
                        window.location.hash = _href;
                    } else {
                        history.pushState(null, null, _href);
                    }
                    fn.statechange(_href, _data);
                } else if($t.hasClass('js-simulate-pushstate')) {
                    e.stopImmediatePropagation();
                    fn.statechange(_href, _data);
                } else if($t.hasClass('js-do-popstate')) {
                    e.stopImmediatePropagation();
                    history.back();
                }
            },
            popstate: function(e, d) {
                var pathname, cur;
                if(o.use_hash){
                    pathname = window.location.hash;
                    cur = pathname.replace('#', '');
                } else {
                    cur = pathname = window.location.pathname;
                }
                if (internal.previous_path == cur && internal.initial_state == cur) {
                    internal.initial_state = false;
                    return;
                }
                fn.statechange(pathname, d);
            },
            pushstate: function(e, d) {
                if(o.use_hash){
                    if(window.location.hash != d.pathname){
                        window.location.hash = d.pathname;
                    }
                } else {
                    if(window.location.pathname != d.pathname){
                        history.pushState(null, null, d.pathname);
                    }
                }
                if(!d || !d.prevent_propagation){
                    fn.statechange(d.pathname, d);
                }
            },
            simulate_pushstate: function(e, d) {
                if(!d || !d.prevent_propagation){
                    fn.statechange(d.pathname, d);
                }
            },
            hashchange: function(e, d) {
                if (!d || !d.prevent_propagation) {
                    fn.statechange(window.location.hash);
                }
            }
        };

        this.get_path_components = fn.get_path_components;

        fn.init();
        console.log(internal);
    }

    PushstateHelper.get_path_components = function(path){
        var components, position;
        if(path){
            components = path.split('/');
            position = components.length;
            while(position--){
                if(!components[position].length){
                    components.splice(position,1);
                }
            }
            return components;
        }
    };

    PushstateHelper.get_get_params = function() {
        var d, get_str, get_components;
        d = {};
        get_str = window.location.search;
        if (!get_str || !get_str.length) {
            return d;
        }
        // first character is always '?'
        get_str = get_str.substring(1);
        get_components = get_str.split('&');
        $.each(get_components, function(i, component) {
            var pair;
            pair = component.split('=');
            if (pair.length) {
                d[pair[0]] = pair[1] ? pair[1] : null;
            }
        });
        return d;
    };

    NI.PushstateHelper = PushstateHelper;

    return PushstateHelper;

});
<|endoftext|>


<commit_before>var ws = require("nodejs-websocket");
var Autolinker = require('autolinker');
var microtime = require("microtime");
var util = require("util");

function htmlspecialchars(string,quote_style,charset,double_encode){var optTemp=0,i=0,noquotes=false;if(typeof quote_style==='undefined'||quote_style===null){quote_style=2}string=string.toString();if(double_encode!==false){string=string.replace(/&/g,'&')}string=string.replace(/</g,'<').replace(/>/g,'>');var OPTS={'ENT_NOQUOTES':0,'ENT_HTML_QUOTE_SINGLE':1,'ENT_HTML_QUOTE_DOUBLE':2,'ENT_COMPAT':2,'ENT_QUOTES':3,'ENT_IGNORE':4};if(quote_style===0){noquotes=true}if(typeof quote_style!=='number'){quote_style=[].concat(quote_style);for(i=0;i<quote_style.length;i++){if(OPTS[quote_style[i]]===0){noquotes=true}else if(OPTS[quote_style[i]]){optTemp=optTemp|OPTS[quote_style[i]]}}quote_style=optTemp}if(quote_style&OPTS.ENT_HTML_QUOTE_SINGLE){string=string.replace(/'/g,''')}if(!noquotes){string=string.replace(/"/g,'"')}return string}

var server = ws.createServer(function (connection) {
	connection.nickname = null;
	connection.timerout = setTimeout(connection.timeout,10000);
	connection.timeout = function(){ broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (Ping timeout)"); connection.close(1011,"Ping Timeout"); }
	connection.on("text", function (str) {
		regPacket = /([A-Z]{4})\s?(.*)/g;
		regMatch = regPacket.exec(str.trim());
		if(regMatch === null) {
			connection.close(500, "Bad Request");
			return;
		}
		Protocol = regMatch[1];

		// No TEXT Part
		if(Protocol == "PING") {
			connection.sendText("PONG");
			clearTimeout(connection.timerout);
			connection.timerout = setTimeout(connection.timeout,10000);
			return;
		}

		// TEXT Part
		regText = htmlspecialchars(regMatch[2], "ENT_QUOTES");

		if(Protocol == "NICK") {
			if (isDuplicateNick(regText)) {
				connection.sendText("ERRO 이미 존재하는 닉네임 입니다");
				return;
			} else {
				if (connection.nickname === null) {
					connection.nickname = regText;
					connection.sendText("HELO");
					broadcast("CHAT " + regText + " 님이 입장하셨습니다");
					return;
				} else {
					var oldNick = connection.nickname;
					connection.nickname = regText;
					broadcast("CHAT " + oldNick + " 님이 닉네임을 " + regText + "로 변경하셨습니다");
					return;
				}
			}
		}

		if (connection.nickname === null) {
			connection.close(401, "Unauthorized");
			return;
		}

		if (Protocol == "CHAT") {
			broadcast("CHAT [" + connection.nickname + "] " + Autolinker.link(regText));
			return;
		} else {
			connection.close(500, "Bad Request");
			return;
		}
	});

	connection.on("close", function () {
		if (connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다");
		}
	});
}).listen(8000);

function isDuplicateNick(nickname) {
	var isDup = false;
	server.connections.forEach(function (connection) {
		if(nickname.toLowerCase() == connection.nickname.toLowerCase()) {
			isDup = true;
		}
	})
	return isDup;
}

function broadcast(str) {
	server.connections.forEach(function (connection) {
		connection.sendText(str);
	})
}<commit_msg>Fix bug<commit_after>var ws = require("nodejs-websocket");
var Autolinker = require('autolinker');
var microtime = require("microtime");
var util = require("util");

function htmlspecialchars(string,quote_style,charset,double_encode){var optTemp=0,i=0,noquotes=false;if(typeof quote_style==='undefined'||quote_style===null){quote_style=2}string=string.toString();if(double_encode!==false){string=string.replace(/&/g,'&')}string=string.replace(/</g,'<').replace(/>/g,'>');var OPTS={'ENT_NOQUOTES':0,'ENT_HTML_QUOTE_SINGLE':1,'ENT_HTML_QUOTE_DOUBLE':2,'ENT_COMPAT':2,'ENT_QUOTES':3,'ENT_IGNORE':4};if(quote_style===0){noquotes=true}if(typeof quote_style!=='number'){quote_style=[].concat(quote_style);for(i=0;i<quote_style.length;i++){if(OPTS[quote_style[i]]===0){noquotes=true}else if(OPTS[quote_style[i]]){optTemp=optTemp|OPTS[quote_style[i]]}}quote_style=optTemp}if(quote_style&OPTS.ENT_HTML_QUOTE_SINGLE){string=string.replace(/'/g,''')}if(!noquotes){string=string.replace(/"/g,'"')}return string}

var server = ws.createServer(function (connection) {
	connection.nickname = null;
	connection.timerout = setTimeout(connection.timeout,10000);
	connection.timeout = function(){ broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다 (Ping timeout)"); connection.close(1011,"Ping Timeout"); }
	connection.on("text", function (str) {
		regPacket = /([A-Z]{4})\s?(.*)/g;
		regMatch = regPacket.exec(str.trim());
		if(regMatch === null) {
			connection.close(500, "Bad Request");
			return;
		}
		Protocol = regMatch[1];

		// No TEXT Part
		if(Protocol == "PING") {
			connection.sendText("PONG");
			clearTimeout(connection.timerout);
			connection.timerout = setTimeout(connection.timeout,10000);
			return;
		}

		// TEXT Part
		regText = htmlspecialchars(regMatch[2], "ENT_QUOTES");

		if(Protocol == "NICK") {
			if (isDuplicateNick(regText)) {
				connection.sendText("ERRO 이미 존재하는 닉네임 입니다");
				return;
			} else {
				if (connection.nickname === null) {
					connection.nickname = regText;
					connection.sendText("HELO");
					broadcast("CHAT " + regText + " 님이 입장하셨습니다");
					return;
				} else {
					var oldNick = connection.nickname;
					connection.nickname = regText;
					broadcast("CHAT " + oldNick + " 님이 닉네임을 " + regText + "로 변경하셨습니다");
					return;
				}
			}
		}

		if (connection.nickname === null) {
			connection.close(401, "Unauthorized");
			return;
		}

		if (Protocol == "CHAT") {
			broadcast("CHAT [" + connection.nickname + "] " + Autolinker.link(regText));
			return;
		} else {
			connection.close(500, "Bad Request");
			return;
		}
	});

	connection.on("close", function () {
		if (connection.nickname !== null) {
			broadcast("CHAT " + connection.nickname + " 님이 퇴장하셨습니다");
		}
	});
}).listen(8000);

function isDuplicateNick(nickname) {
	var isDup = false;
	server.connections.forEach(function (connection) {
		if(connection.nickname != null) {
			if(nickname.toLowerCase() == connection.nickname.toLowerCase()) {
				isDup = true;
			}
		}
	})
	return isDup;
}

function broadcast(str) {
	server.connections.forEach(function (connection) {
		connection.sendText(str);
	})
}<|endoftext|>


<commit_before>/*
 * Home Controller
 */
function HomeCtrl($scope, $location, $window, Map)
{
	var map_marker = '/img/target.png';

	function _init()
	{
		$scope.year 		 = (new Date()).getFullYear();
		$scope.zoom 		 = 1;
		$scope.latitude  = 0;
		$scope.longitude = 0;
		$scope.separator  = 'comma';
		$scope.projection = 'EPSG:4326';
		$scope.defaultProjection = 'EPSG:4326';

		Map.init({
			id: 'map',
			startZoom: $scope.zoom,
			startPoint: { lon: 0, lat: 0 },
			onSelectPoint: $scope.onSelectPoint
		});

		Map.getActualZoom(function(zoom) {
			$scope.zoom = zoom;
			_applyPhase();
		});

		Map.enableDragPoint(function(point) {
			_updateValues(point);
		});

		$scope.dropMarker();

		angular.element($window).bind('resize', function() { Map.fixMapHeight(); });
	}

	function _applyPhase()
	{
		if(!$scope.$$phase) $scope.$apply();
	};

	function _separator()
	{
		switch($scope.separator)
		{
			case 'space': return ' ';
			case 'comma': return ', ';
		}
	};

	function _updateValues(point)
	{
		$scope.actualPoint = point;

		var lonlat = { x: point.lon, y: point.lat }
		var point = Map.xy2lonlat(lonlat);

		if($scope.projection !== $scope.defaultProjection)
		{
			point = Map.transform(point, $scope.defaultProjection, $scope.projection);
		}

		$scope.longitude = point.lon;
		$scope.latitude  = point.lat;
		$scope.latlon = point.lat + _separator() + point.lon;
		$scope.lonlat = point.lon + _separator() + point.lat;

		_applyPhase();
	};

	function _addMarker(point)
	{
		point.icon = map_marker;

		Map.addPoint(point, {
			layer: 'position'
		});

		_updateValues(point);
	};

	$scope.goto = function(to)
	{
		$location.path(to);
	};

	$scope.dropMarker = function(point)
	{
		if (!point)
		{
			point = Map.getCenter();
		}

		_addMarker(point);
	};

	$scope.getPosition = function()
	{
		$scope.gettingPosition = true;

		Map.getPosition(function(point) {
			_addMarker(point);
			Map.setCenterMap(point, 7);
		}, function(errorMessage) {
			window.alert(errorMessage);
		}, function() {
			// always execute after success and error
			$scope.gettingPosition = false;
		});
	};

	$scope.updateValues = function()
	{
		_updateValues($scope.actualPoint);
	};

	$scope.onSelectPoint = function(feature)
	{
		var content = '
' + feature.data.place + '
' + feature.data.temperatures + '
';

		Map.showPopup({
			content:  content,
			position: feature.geometry
		});
	};

	_init();
};

angular
	.module('app.controllers')
	.controller('HomeCtrl', ['$scope', '$location', '$window', 'Map', HomeCtrl]);
<commit_msg>aumentado zoom apos usar geolocation<commit_after>/*
 * Home Controller
 */
function HomeCtrl($scope, $location, $window, Map)
{
	var map_marker = '/img/target.png';

	function _init()
	{
		$scope.year 		 = (new Date()).getFullYear();
		$scope.zoom 		 = 1;
		$scope.latitude  = 0;
		$scope.longitude = 0;
		$scope.separator  = 'comma';
		$scope.projection = 'EPSG:4326';
		$scope.defaultProjection = 'EPSG:4326';

		Map.init({
			id: 'map',
			startZoom: $scope.zoom,
			startPoint: { lon: 0, lat: 0 },
			onSelectPoint: $scope.onSelectPoint
		});

		Map.getActualZoom(function(zoom) {
			$scope.zoom = zoom;
			_applyPhase();
		});

		Map.enableDragPoint(function(point) {
			_updateValues(point);
		});

		$scope.dropMarker();

		angular.element($window).bind('resize', function() { Map.fixMapHeight(); });
	}

	function _applyPhase()
	{
		if(!$scope.$$phase) $scope.$apply();
	};

	function _separator()
	{
		switch($scope.separator)
		{
			case 'space': return ' ';
			case 'comma': return ', ';
		}
	};

	function _updateValues(point)
	{
		$scope.actualPoint = point;

		var lonlat = { x: point.lon, y: point.lat }
		var point = Map.xy2lonlat(lonlat);

		if($scope.projection !== $scope.defaultProjection)
		{
			point = Map.transform(point, $scope.defaultProjection, $scope.projection);
		}

		$scope.longitude = point.lon;
		$scope.latitude  = point.lat;
		$scope.latlon = point.lat + _separator() + point.lon;
		$scope.lonlat = point.lon + _separator() + point.lat;

		_applyPhase();
	};

	function _addMarker(point)
	{
		point.icon = map_marker;

		Map.addPoint(point, {
			layer: 'position'
		});

		_updateValues(point);
	};

	$scope.goto = function(to)
	{
		$location.path(to);
	};

	$scope.dropMarker = function(point)
	{
		if (!point)
		{
			point = Map.getCenter();
		}

		_addMarker(point);
	};

	$scope.getPosition = function()
	{
		$scope.gettingPosition = true;

		Map.getPosition(function(point) {
			_addMarker(point);
			Map.setCenterMap(point, 10);
		}, function(errorMessage) {
			window.alert(errorMessage);
		}, function() {
			// always execute after success and error
			$scope.gettingPosition = false;
		});
	};

	$scope.updateValues = function()
	{
		_updateValues($scope.actualPoint);
	};

	$scope.onSelectPoint = function(feature)
	{
		var content = '
' + feature.data.place + '
' + feature.data.temperatures + '
';

		Map.showPopup({
			content:  content,
			position: feature.geometry
		});
	};

	_init();
};

angular
	.module('app.controllers')
	.controller('HomeCtrl', ['$scope', '$location', '$window', 'Map', HomeCtrl]);
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var koa = require('koa');
var router = require('koa-router')();
var serve = require('koa-static');
var koaBody = require('koa-body');
var gzip = require('koa-gzip');

var app = koa();
var iwebRouter = require('./router');

// uui定制
var customized = require("./customized");
var down = require("./down");

iwebRouter.setRouters(router, '.');

app.use(gzip());

app.use(koaBody({
  formidable: {uploadDir: __dirname},
  textLimit: '50mb',
  formLimit: '50mb'
}));

app.use(router.routes())
  .use(router.allowedMethods());

// response
app.use(function *(next){
  // (3) 进入 response 中间件，没有捕获到下一个符合条件的中间件，传递到 upstream
  if (this.request.url === '/') {
    this.body = fs.readFileSync(path.resolve(__dirname, '../dist/index.html')).toString();
  } else {
    return yield* next;
  }
});

app.use(serve(path.join(__dirname, '../')));

app.listen( 8001 );

// 起服务时清楚定制生成的临时文件同时创建临时scss文件
// deleteFolderRecursive(path.resolve(__dirname, '../dist/pages/custom/temp/'));

// fs.exists( path.resolve(__dirname, '../dist/pages/custom/themeColors.scss'), function(exist) {
//     if(!exist){
//         fs.writeFile(path.resolve(__dirname, '../dist/pages/custom/themeColors.scss'),'');
//     }
// });

// fs.exists( path.resolve(__dirname, '../dist/pages/custom/customized.scss'), function(exist) {
//     if(!exist){
//         fs.writeFile(path.resolve(__dirname, '../dist/pages/custom/customized.scss'),'');
//     }
// });

console.log('server started at http://localhost:8001');

function deleteFolderRecursive(path) {
    var files = [];
    if( fs.existsSync(getResolvePath(path)) ) {
        files = fs.readdirSync(getResolvePath(path));
        files.forEach(function(file,index){
            var curPath = path + "/" + file;
            if(fs.statSync(getResolvePath(curPath)).isDirectory()) {
                deleteFolderRecursive(curPath);
            } else {
                fs.unlinkSync(getResolvePath(curPath));
            }
        });
        fs.rmdirSync(getResolvePath(path));
    }
};

function getResolvePath(p){
	return path.resolve(__dirname, p)
}
<commit_msg>add: maxage<commit_after>var fs = require('fs');
var path = require('path');
var koa = require('koa');
var router = require('koa-router')();
var serve = require('koa-static');
var koaBody = require('koa-body');
var gzip = require('koa-gzip');

var app = koa();
var iwebRouter = require('./router');

// uui定制
var customized = require("./customized");
var down = require("./down");

iwebRouter.setRouters(router, '.');

app.use(gzip());

app.use(koaBody({
  formidable: {uploadDir: __dirname},
  textLimit: '50mb',
  formLimit: '50mb'
}));

app.use(router.routes())
  .use(router.allowedMethods());

// response
app.use(function *(next){
  // (3) 进入 response 中间件，没有捕获到下一个符合条件的中间件，传递到 upstream
  if (this.request.url === '/') {
    this.body = fs.readFileSync(path.resolve(__dirname, '../dist/index.html')).toString();
  } else {
    return yield* next;
  }
});

app.use(serve(path.join(__dirname, '../'),{maxAge: 2592000000}));

app.listen( 8001 );

// 起服务时清楚定制生成的临时文件同时创建临时scss文件
// deleteFolderRecursive(path.resolve(__dirname, '../dist/pages/custom/temp/'));

// fs.exists( path.resolve(__dirname, '../dist/pages/custom/themeColors.scss'), function(exist) {
//     if(!exist){
//         fs.writeFile(path.resolve(__dirname, '../dist/pages/custom/themeColors.scss'),'');
//     }
// });

// fs.exists( path.resolve(__dirname, '../dist/pages/custom/customized.scss'), function(exist) {
//     if(!exist){
//         fs.writeFile(path.resolve(__dirname, '../dist/pages/custom/customized.scss'),'');
//     }
// });

console.log('server started at http://localhost:8001');

function deleteFolderRecursive(path) {
    var files = [];
    if( fs.existsSync(getResolvePath(path)) ) {
        files = fs.readdirSync(getResolvePath(path));
        files.forEach(function(file,index){
            var curPath = path + "/" + file;
            if(fs.statSync(getResolvePath(curPath)).isDirectory()) {
                deleteFolderRecursive(curPath);
            } else {
                fs.unlinkSync(getResolvePath(curPath));
            }
        });
        fs.rmdirSync(getResolvePath(path));
    }
};

function getResolvePath(p){
	return path.resolve(__dirname, p)
}
<|endoftext|>


<commit_before>import os from 'os';
import semver from 'semver';
import { remote } from 'electron';
import { autorun } from 'mobx';

import { isMac } from '../environment';

export default class FranzTouchBar {
  constructor(stores, actions) {
    this.stores = stores;
    this.actions = actions;

    // Temporary fix for https://github.com/electron/electron/issues/10442
    // TODO: remove when we upgrade to electron 1.8.2 or later
    try {
      if (isMac && semver.gt(os.release(), '16.6.0')) {
        this.build = autorun(this._build.bind(this));
      }
    } catch (err) {
      console.error(err);
    }
  }

  _build() {
    const currentWindow = remote.getCurrentWindow();

    if (this.stores.user.isLoggedIn) {
      const { TouchBar } = remote;
      const { TouchBarButton, TouchBarSpacer } = TouchBar;

      const buttons = [];
      this.stores.services.enabled.forEach(((service) => {
        buttons.push(new TouchBarButton({
          label: `${service.name}${service.unreadDirectMessageCount > 0
            ? ' 🔴' : ''} ${service.unreadDirectMessageCount === 0
              && service.unreadIndirectMessageCount > 0
            ? ' ⚪' : ''}`,
          backgroundColor: service.isActive ? '#3498DB' : null,
          click: () => {
            this.actions.service.setActive({ serviceId: service.id });
          },
        }), new TouchBarSpacer({ size: 'small' }));
      }));

      const touchBar = new TouchBar({ items: buttons });
      currentWindow.setTouchBar(touchBar);
    } else {
      currentWindow.setTouchBar(null);
    }
  }
}
<commit_msg>fix(macOS): Only show services in Touch Bar that should be visible<commit_after>import os from 'os';
import semver from 'semver';
import { remote } from 'electron';
import { autorun } from 'mobx';

import { isMac } from '../environment';

export default class FranzTouchBar {
  constructor(stores, actions) {
    this.stores = stores;
    this.actions = actions;

    // Temporary fix for https://github.com/electron/electron/issues/10442
    // TODO: remove when we upgrade to electron 1.8.2 or later
    try {
      if (isMac && semver.gt(os.release(), '16.6.0')) {
        this.build = autorun(this._build.bind(this));
      }
    } catch (err) {
      console.error(err);
    }
  }

  _build() {
    const currentWindow = remote.getCurrentWindow();

    if (this.stores.user.isLoggedIn) {
      const { TouchBar } = remote;
      const { TouchBarButton, TouchBarSpacer } = TouchBar;

      const buttons = [];
      this.stores.services.allDisplayed.forEach(((service) => {
        buttons.push(new TouchBarButton({
          label: `${service.name}${service.unreadDirectMessageCount > 0
            ? ' 🔴' : ''} ${service.unreadDirectMessageCount === 0
              && service.unreadIndirectMessageCount > 0
            ? ' ⚪' : ''}`,
          backgroundColor: service.isActive ? '#3498DB' : null,
          click: () => {
            this.actions.service.setActive({ serviceId: service.id });
          },
        }), new TouchBarSpacer({ size: 'small' }));
      }));

      const touchBar = new TouchBar({ items: buttons });
      currentWindow.setTouchBar(touchBar);
    } else {
      currentWindow.setTouchBar(null);
    }
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import SPELLS from 'common/SPELLS/index';
import SpellIcon from 'common/SpellIcon';
import SpellLink from 'common/SpellLink';
import ItemDamageDone from 'Main/ItemDamageDone';
import Wrapper from 'common/Wrapper';

class AspectOfTheBeast extends Analyzer {

  static dependencies = {
    combatants: Combatants,
  };

  damage = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasTalent(SPELLS.ASPECT_OF_THE_BEAST_TALENT.id);
  }

  on_byPlayerPet_damage(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.ASPECT_OF_THE_BEAST_BESTIAL_FEROCITY.id) {
      return;
    }
    this.damage += event.amount + (event.absorbed || 0);
  }
  get aspectOfTheBeastDamageThreshold() {
    return {
      actual: this.damage,
      isLessThan: {
        minor: 3,
        average: 2,
        major: 1,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    when(this.aspectOfTheBeastDamageThreshold).addSuggestion((suggest) => {
      return suggest(<Wrapper><SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} /> had no damage contribution, which indiciates you did not have your pet specced into Ferocity, which it should always be.</Wrapper>)
        .icon(SPELLS.ASPECT_OF_THE_BEAST_TALENT.icon)
        .actual(`Aspect of the Beast did no additional damage`)
        .recommended(`Speccing your pet into Ferocity is recommended`);
    });
  }

  subStatistic() {
    return (

          <SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id}>
            <SpellIcon id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} noLink /> Bestial Ferocity
          </SpellLink>

          <ItemDamageDone amount={this.damage} />

    );
  }
}

export default AspectOfTheBeast;
<commit_msg>remove index<commit_after>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import SPELLS from 'common/SPELLS';
import SpellIcon from 'common/SpellIcon';
import SpellLink from 'common/SpellLink';
import ItemDamageDone from 'Main/ItemDamageDone';
import Wrapper from 'common/Wrapper';

class AspectOfTheBeast extends Analyzer {

  static dependencies = {
    combatants: Combatants,
  };

  damage = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasTalent(SPELLS.ASPECT_OF_THE_BEAST_TALENT.id);
  }

  on_byPlayerPet_damage(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.ASPECT_OF_THE_BEAST_BESTIAL_FEROCITY.id) {
      return;
    }
    this.damage += event.amount + (event.absorbed || 0);
  }
  get aspectOfTheBeastDamageThreshold() {
    return {
      actual: this.damage,
      isLessThan: {
        minor: 3,
        average: 2,
        major: 1,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    when(this.aspectOfTheBeastDamageThreshold).addSuggestion((suggest) => {
      return suggest(<Wrapper><SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} /> had no damage contribution, which indiciates you did not have your pet specced into Ferocity, which it should always be.</Wrapper>)
        .icon(SPELLS.ASPECT_OF_THE_BEAST_TALENT.icon)
        .actual(`Aspect of the Beast did no additional damage`)
        .recommended(`Speccing your pet into Ferocity is recommended`);
    });
  }

  subStatistic() {
    return (

          <SpellLink id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id}>
            <SpellIcon id={SPELLS.ASPECT_OF_THE_BEAST_TALENT.id} noLink /> Bestial Ferocity
          </SpellLink>

          <ItemDamageDone amount={this.damage} />

    );
  }
}

export default AspectOfTheBeast;
<|endoftext|>


<commit_before>var fs = require('fs'),
    xml = require('xml-object-stream'),
    _ = require('lodash'),
    moment = require('moment'),
    utils = require('../shared/utils')

exports.readPrograms = function (body, callback) {
  var stream = xml.parse(body)
  var programs = []

  var validate = _.reduce([
    required('ALKUPERAINENNIMI', 'name'),
    optional('SUOMALAINENNIMI', 'name-fi'),
    optional('RUOTSALAINENNIMI', 'name-sv'),
    optional('MUUNIMI', 'name-other'),
    optional('VALMISTUMISVUOSI', 'year'),
    map(optional('MAAT', 'country'), function(p) { return p.country ? {country: p.country.split(' ')} : {country: []} }),
    optional('TUOTANTOYHTIO', 'legacy-production-companies'),
    map(requiredAttr('TYPE', 'type'), function(p) { return { type: legacyProgramTypes[p.type] }}),
    function(xml) { return {
      program: {'legacy-genre': optionListToArray(xml.LAJIT).map(function(g) { return legacyGenres[g] })
          .concat(optionListToArray(xml['TELEVISIO-OHJELMALAJIT']).map(function(g) { return legacyTvGenres[g] }))
          .concat(optionListToArray(xml.PELINLAJIT))},
      errors: []
    }},
    map(childrenByNameTo('OHJAAJA', 'directors'), function(p) { return {directors: p.directors.map(fullname) }}),
    map(childrenByNameTo('NAYTTELIJA', 'actors'), function(p) { return {actors: p.actors.map(fullname) }})
  ], function(acc, f) {
    return flatMap(acc, function(_) { return f })
  }, ret({}))

  stream.each('KUVAOHJELMA', function(program) {
    var criteriaComments = _.object(childrenByName(program.LUOKITTELU, 'VALITTUTERMI').map(function(c) {
      return [parseInt(c.$.KRITEERI), c.$.KOMMENTTI]
    }))
    var now = new Date()

    programs.push(validate(program))

    /*
    programs.push({
      valid: true,
      program: {
        name: [program.ALKUPERAINENNIMI.$text],
        'name-fi': [program.SUOMALAINENNIMI.$text],
        'name-sv': [program.RUOTSALAINENNIMI.$text],
        'name-other': [program.MUUNIMI.$text],
        year: program.VALMISTUMISVUOSI.$text,
        country: program.MAAT.$text ? program.MAAT.$text.split(' ') : [],
        'legacy-production-companies': program.TUOTANTOYHTIO.$text,
        'program-type': legacyProgramTypes[program.$.TYPE],
        'legacy-genre': optionListToArray(program.LAJIT).map(function(g) { return legacyGenres[g] })
          .concat(optionListToArray(program['TELEVISIO-OHJELMALAJIT']).map(function(g) { return legacyTvGenres[g] }))
          .concat(optionListToArray(program.PELINLAJIT)),
        directors: childrenByName(program, 'OHJAAJA').map(fullname),
        actors: childrenByName(program, 'NAYTTELIJA').map(fullname),
        synopsis: program.SYNOPSIS.$text,
        season: optional(program.TUOTANTOKAUSI),
        episode: optional(program.OSA),
        //gameFormat:
        classification: {
          //author: null,
          format: optional(program.LUOKITTELU.FORMAATTI),
          duration: optional(program.LUOKITTELU.KESTO), // for now matches a regexp in the client
          safe: _.isEmpty(criteriaComments) ? true : false,
          criteria: _.keys(criteriaComments),
          'criteria-comments': criteriaComments,
          'creation-date': now,
          'registration-date': moment(program.LUOKITTELU.$.REKISTEROINTIPAIVA, "DD.MM.YYYY HH:mm:ss").toDate(),
          status: 'registered'
        }
      }
    })
    */
  })
  stream.on('end', function() {
    callback(null, programs)
  })
}

// validator = Xml -> Result
// validation = validator -> (program -> validator) -> validator
function flatMap(validator, f) {
  return function(xml) {
    var res = validator(xml)
    var res2 = f(res.program)(xml)
    return {program: _.merge(res.program, res2.program), errors: res.errors.concat(res2.errors)}
  }
}

function map(validator, f) {
  return function(xml) {
    var res = validator(xml)
    return {program: f(res.program), errors: []}
  }
}

function ret(program) {
  return function(xml) {
    return {program: program, errors: []}
  }
}

function required(name, toField) {
  return function(xml) {
    if (xml[name]) return {program: _.object([[toField, xml[name].$text]]), errors: []}
    else return {program: {}, errors: ["Missing required field " + name]}
  }
}

function requiredAttr(name, toField) {
  return function(xml) {
    if (xml.$[name]) return {program: utils.keyValue(toField, xml.$[name]), errors: []}
    else return {program: {}, errors: ["Missing required attribute: " + name]}
  }
}

function optional(field, toField) {
  return function(xml) {
    if (!xml[field] || !xml[field].$text || xml[field].$text.length == 0) return {program: utils.keyValue(toField, undefined), errors: []}
    else return {program: utils.keyValue(toField, xml[field].$text), errors: []}
  }
}

function childrenByNameTo(field, toField) {
  return function(xml) {
    return {
      program: utils.keyValue(toField, childrenByName(xml, field)),
      errors: []
    }
  }
}

function fullname(node) {
  return node.ETUNIMI.$text + ' ' + node.SUKUNIMI.$text
}
function childrenByName(root, name) {
  return root.$children.filter(function(e) { return e.$name == name })
}

function optionListToArray(field) {
  if (!field || field.$text.length == 0) return []
  var arr = field.$text.split(',').map(function(s) { return s.replace(/[\^\s]/g, '')} )
  return _(arr).compact().uniq().value()
}

var legacyGenres = {
  '1': 'Fiktio',
  '2': 'Animaatio',
  '3': 'Viihde',
  '4': 'Seksi / Erotiikka',
  '5': 'Dokumentti',
  '6': 'Lasten ohjelmat',
  '9': 'Muut',
  '1a': 'Romantiikka',
  '1b': 'Draama',
  '1c': 'Historiallinen näytelmä',
  '1d': 'Trilleri',
  '1e': 'Seikkailu',
  '1f': 'Western',
  '1g': 'Sota',
  '1h': 'Kauhu',
  '1j': 'Tieteisseikkailu',
  '1k': 'Toimintaelokuva',
  '1m': 'Fantasia',
  '1n': 'Komedia ja farssi',
  '3c': 'Musiikki',
  '5a': 'Opetus',
  '5b': 'Urheilu',
  '5c': 'Matkailu',
  '5d': 'Henkilödokumentti',
  '5e': 'Luontodokumentti',
  '6a': 'Lasten animaatio',
  '6b': 'Lasten fiktio',
  '6c': 'Muu lastenelokuva',
  '9a': 'Mainonta',
  '9c': 'Tietoisku',
  '9d': 'Kokeiluelokuva',
  '9e': 'Videotaide',
  '7a': 'Trailer',
  '7b': 'Extra'
}
var legacyTvGenres = {
  '2': 'Ajankohtaisohjelmat',
  '3': 'Asiaohjelmat/kulttuuri/lifestyle',
  '4': 'Urheilu',
  '5': 'Kotimainen fiktio',
  '6': 'Ulkomainen fiktio',
  '7': 'Elokuvat',
  '8': 'Lasten ohjelmat',
  '9': 'Opetus- ja tiedeohjelmat',
  '10': 'Viihde/kevyt musiikki/reality',
  '11': 'Muu musiikki',
  '12': 'Muut ohjelmat',
  '1.': 'Uutiset',
  '1.1': 'Vakiouutiset',
  '1.2': 'Muut uutislähetykset',
  '3.1': 'Asiaohjelmat/lifestyle',
  '3.2': 'Kulttuuriohjelmat',
  '4.1': 'Urheilu-uutiset',
  '4.2': 'Muu urheilu',
  '7.1': 'Kotimaiset elokuvat',
  '7.2': 'Ulkomaiset elokuvat',
  '12.1': 'Ostos-TV',
  '12.2': 'WWW (peliohjelmat, chatit)',
  '10.1': 'Kotimainen viihde/kevyt musiikki/reality',
  '10.2': 'Ulkomainen viihde/kevyt musiikki/reality',
  '13': 'Populaarikulttuuri'
}

var legacyProgramTypes = {
  '01': 1,       //'Kotimainen elokuva' -> movie
  '02': 1,       //'Ulkomainen elokuva' -> movie
  '02b': 0,    // 'TESTI' -> unknown
  '03': 3,       //'TV-sarjan jakso' -> tv
  '04': 3,       // 'Muu tv-ohjelma' -> tv
  '05': 2,       // 'TV-sarjan nimi' -> series
  '06': 5,       // 'Traileri' -> trailer
  '07': 4,       // 'Extra' -> extra
  '08': 6,       // 'Peli' -> game
  '10': 0,      // 'Yhteistuotanto' -> unknown
  '11': 7,      // 'PEGI hyväksytty peli' -> game
  '12': 0       // 'Muu kuvaohjelma' -> unknown
}
<commit_msg>Add some validations<commit_after>var fs = require('fs'),
    xml = require('xml-object-stream'),
    _ = require('lodash'),
    moment = require('moment'),
    utils = require('../shared/utils')

exports.readPrograms = function (body, callback) {
  var stream = xml.parse(body)
  var programs = []

  var validate = _.reduce([
    required('ALKUPERAINENNIMI', 'name'),
    optional('SUOMALAINENNIMI', 'name-fi'),
    optional('RUOTSALAINENNIMI', 'name-sv'),
    optional('MUUNIMI', 'name-other'),
    optional('VALMISTUMISVUOSI', 'year'),
    map(optional('MAAT', 'country'), function(p) { return p.country ? {country: p.country.split(' ')} : {country: []} }),
    optional('TUOTANTOYHTIO', 'legacy-production-companies'),
    map(requiredAttr('TYPE', 'type'), function(p) { return { type: legacyProgramTypes[p.type] }}),
    required('SYNOPSIS', 'synopsis'),
    function(xml) { return {
      program: {'legacy-genre': optionListToArray(xml.LAJIT).map(function(g) { return legacyGenres[g] })
          .concat(optionListToArray(xml['TELEVISIO-OHJELMALAJIT']).map(function(g) { return legacyTvGenres[g] }))
          .concat(optionListToArray(xml.PELINLAJIT))},
      errors: []
    }},
    map(childrenByNameTo('OHJAAJA', 'directors'), function(p) { return {directors: p.directors.map(fullname) }}),
    map(childrenByNameTo('NAYTTELIJA', 'actors'), function(p) { return {actors: p.actors.map(fullname) }})
  ], function(acc, f) {
    return flatMap(acc, function(_) { return f })
  }, ret({}))

  stream.each('KUVAOHJELMA', function(program) {
    var criteriaComments = _.object(childrenByName(program.LUOKITTELU, 'VALITTUTERMI').map(function(c) {
      return [parseInt(c.$.KRITEERI), c.$.KOMMENTTI]
    }))
    var now = new Date()

    programs.push(validate(program))

    /*
    programs.push({
      valid: true,
      program: {
        name: [program.ALKUPERAINENNIMI.$text],
        'name-fi': [program.SUOMALAINENNIMI.$text],
        'name-sv': [program.RUOTSALAINENNIMI.$text],
        'name-other': [program.MUUNIMI.$text],
        year: program.VALMISTUMISVUOSI.$text,
        country: program.MAAT.$text ? program.MAAT.$text.split(' ') : [],
        'legacy-production-companies': program.TUOTANTOYHTIO.$text,
        'program-type': legacyProgramTypes[program.$.TYPE],
        'legacy-genre': optionListToArray(program.LAJIT).map(function(g) { return legacyGenres[g] })
          .concat(optionListToArray(program['TELEVISIO-OHJELMALAJIT']).map(function(g) { return legacyTvGenres[g] }))
          .concat(optionListToArray(program.PELINLAJIT)),
        directors: childrenByName(program, 'OHJAAJA').map(fullname),
        actors: childrenByName(program, 'NAYTTELIJA').map(fullname),
        synopsis: program.SYNOPSIS.$text,
        season: optional(program.TUOTANTOKAUSI),
        episode: optional(program.OSA),
        //gameFormat:
        classification: {
          //author: null,
          format: optional(program.LUOKITTELU.FORMAATTI),
          duration: optional(program.LUOKITTELU.KESTO), // for now matches a regexp in the client
          safe: _.isEmpty(criteriaComments) ? true : false,
          criteria: _.keys(criteriaComments),
          'criteria-comments': criteriaComments,
          'creation-date': now,
          'registration-date': moment(program.LUOKITTELU.$.REKISTEROINTIPAIVA, "DD.MM.YYYY HH:mm:ss").toDate(),
          status: 'registered'
        }
      }
    })
    */
  })
  stream.on('end', function() {
    callback(null, programs)
  })
}

// validator = Xml -> Result
// validation = validator -> (program -> validator) -> validator
function flatMap(validator, f) {
  return function(xml) {
    var res = validator(xml)
    var res2 = f(res.program)(xml)
    return {program: _.merge(res.program, res2.program), errors: res.errors.concat(res2.errors)}
  }
}

function map(validator, f) {
  return function(xml) {
    var res = validator(xml)
    return {program: f(res.program), errors: []}
  }
}

function ret(program) {
  return function(xml) {
    return {program: program, errors: []}
  }
}

function required(name, toField) {
  return function(xml) {
    if (xml[name]) return {program: _.object([[toField, xml[name].$text]]), errors: []}
    else return {program: {}, errors: ["Missing required field " + name]}
  }
}

function requiredAttr(name, toField) {
  return function(xml) {
    if (xml.$[name]) return {program: utils.keyValue(toField, xml.$[name]), errors: []}
    else return {program: {}, errors: ["Missing required attribute: " + name]}
  }
}

function optional(field, toField) {
  return function(xml) {
    if (!xml[field] || !xml[field].$text || xml[field].$text.length == 0) return {program: utils.keyValue(toField, undefined), errors: []}
    else return {program: utils.keyValue(toField, xml[field].$text), errors: []}
  }
}

function childrenByNameTo(field, toField) {
  return function(xml) {
    return {
      program: utils.keyValue(toField, childrenByName(xml, field)),
      errors: []
    }
  }
}

function fullname(node) {
  return node.ETUNIMI.$text + ' ' + node.SUKUNIMI.$text
}
function childrenByName(root, name) {
  return root.$children.filter(function(e) { return e.$name == name })
}

function optionListToArray(field) {
  if (!field || field.$text.length == 0) return []
  var arr = field.$text.split(',').map(function(s) { return s.replace(/[\^\s]/g, '')} )
  return _(arr).compact().uniq().value()
}

var legacyGenres = {
  '1': 'Fiktio',
  '2': 'Animaatio',
  '3': 'Viihde',
  '4': 'Seksi / Erotiikka',
  '5': 'Dokumentti',
  '6': 'Lasten ohjelmat',
  '9': 'Muut',
  '1a': 'Romantiikka',
  '1b': 'Draama',
  '1c': 'Historiallinen näytelmä',
  '1d': 'Trilleri',
  '1e': 'Seikkailu',
  '1f': 'Western',
  '1g': 'Sota',
  '1h': 'Kauhu',
  '1j': 'Tieteisseikkailu',
  '1k': 'Toimintaelokuva',
  '1m': 'Fantasia',
  '1n': 'Komedia ja farssi',
  '3c': 'Musiikki',
  '5a': 'Opetus',
  '5b': 'Urheilu',
  '5c': 'Matkailu',
  '5d': 'Henkilödokumentti',
  '5e': 'Luontodokumentti',
  '6a': 'Lasten animaatio',
  '6b': 'Lasten fiktio',
  '6c': 'Muu lastenelokuva',
  '9a': 'Mainonta',
  '9c': 'Tietoisku',
  '9d': 'Kokeiluelokuva',
  '9e': 'Videotaide',
  '7a': 'Trailer',
  '7b': 'Extra'
}
var legacyTvGenres = {
  '2': 'Ajankohtaisohjelmat',
  '3': 'Asiaohjelmat/kulttuuri/lifestyle',
  '4': 'Urheilu',
  '5': 'Kotimainen fiktio',
  '6': 'Ulkomainen fiktio',
  '7': 'Elokuvat',
  '8': 'Lasten ohjelmat',
  '9': 'Opetus- ja tiedeohjelmat',
  '10': 'Viihde/kevyt musiikki/reality',
  '11': 'Muu musiikki',
  '12': 'Muut ohjelmat',
  '1.': 'Uutiset',
  '1.1': 'Vakiouutiset',
  '1.2': 'Muut uutislähetykset',
  '3.1': 'Asiaohjelmat/lifestyle',
  '3.2': 'Kulttuuriohjelmat',
  '4.1': 'Urheilu-uutiset',
  '4.2': 'Muu urheilu',
  '7.1': 'Kotimaiset elokuvat',
  '7.2': 'Ulkomaiset elokuvat',
  '12.1': 'Ostos-TV',
  '12.2': 'WWW (peliohjelmat, chatit)',
  '10.1': 'Kotimainen viihde/kevyt musiikki/reality',
  '10.2': 'Ulkomainen viihde/kevyt musiikki/reality',
  '13': 'Populaarikulttuuri'
}

var legacyProgramTypes = {
  '01': 1,       //'Kotimainen elokuva' -> movie
  '02': 1,       //'Ulkomainen elokuva' -> movie
  '02b': 0,    // 'TESTI' -> unknown
  '03': 3,       //'TV-sarjan jakso' -> tv
  '04': 3,       // 'Muu tv-ohjelma' -> tv
  '05': 2,       // 'TV-sarjan nimi' -> series
  '06': 5,       // 'Traileri' -> trailer
  '07': 4,       // 'Extra' -> extra
  '08': 6,       // 'Peli' -> game
  '10': 0,      // 'Yhteistuotanto' -> unknown
  '11': 7,      // 'PEGI hyväksytty peli' -> game
  '12': 0       // 'Muu kuvaohjelma' -> unknown
}
<|endoftext|>


<commit_before>'use strict';

CMAQ.factory('api', function ($window, $q, $http, config, data, viewport, storage, state, oauth) {
  var api = {};
  var url = config.url + '/api';

  var unsynced = {
    points: []
  };

  api.online = function () {
    var deferred = $q.defer();

    $http.get('//' + $window.location.hostname).then(
      function () {
        viewport.offline = false;
        deferred.resolve();
      },
      function () {
        viewport.offline = true;
        deferred.reject();
      }
    );

    return deferred.promise;
  };

  api.sync = function () {
    var deferred = $q.defer();
    var totalPoints = 0;

    function resolve(index, total) {
      if (index + 1 === total) {
        unsynced.points = [];
        deferred.resolve();
      }
    }

    function syncMeasurements(point, pointIndex, totalPoints) {
      var total = 0;

      if (!_.isEmpty(point.measurements)) {
        total += point.measurements.length;

        _.each(point.measurements, function (measurement, index) {
          if (measurement.deleted) {
            api.removeMeasurement(measurement.id, point.id).finally(function () {
              if (index + 1 === total) {
                resolve(pointIndex, totalPoints);
              }
            });
          } else {
            if ((_.isString(measurement.id) && measurement.id.indexOf('x') > -1)) {
              api.startMeasurement(measurement, point.id).finally(function () {
                if (index + 1 === total) {
                  resolve(pointIndex, totalPoints);
                }
              });
            } else if (measurement.updated) {
              api.updatedMeasurement(measurement, point.id).finally(function () {
                if (index + 1 === total) {
                  resolve(pointIndex, totalPoints);
                }
              });
            }
          }
        });
      } else {
        resolve(pointIndex, totalPoints);
      }
    }

    if (_.isEmpty(unsynced.points)) {
      if (!_.isEmpty(data.unsynced.points)) {
        unsynced.points = _.cloneDeep(data.unsynced.points);
        totalPoints += unsynced.points.length;

        _.each(_.cloneDeep(unsynced.points), function (point, pointIndex) {
          if (point.deleted) {
            api.deletePoint(point.id).finally(function () {
              resolve(pointIndex, totalPoints);
            });
          } else {
            if ((_.isString(point.id) && point.id.indexOf('x') > -1)) {
              api.addPoint(point).then(
                function (addedPoint) {
                  point.id = addedPoint.id;
                  syncMeasurements(point, pointIndex, totalPoints);
                },
                function () {
                  resolve(pointIndex, totalPoints);
                }
              );
            }
          }
        });
      } else {
        deferred.resolve();
      }
    } else {
      deferred.resolve();
    }

    return deferred.promise;
  };

  api.getPoints = function () {
    var deferred = $q.defer();
    var points = storage.get('POINTS');

    viewport.calling = true;

    data.points = [];

    if (!_.isEmpty(points)) {
      points = JSON.parse(points);
    } else {
      points = undefined;
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.get(url + '/airquality/points/').then(
              function (retrievedPoints) {
                data.points = retrievedPoints;
                deferred.resolve(data.points);
              },
              function (error) {
                if (points) {
                  data.points = points;
                }

                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (points) {
          data.points = points;
        }

        viewport.calling = false;
        deferred.resolve(data.points);
      }
    );

    return deferred.promise;
  };

  api.addPoint = function (point) {
    var deferred = $q.defer();

    if (_.isUndefined(point)) {
      throw new Error('Point not specified');
    } else if (!_.isPlainObject(point)) {
      throw new Error('Point must be plain object');
    }

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.post(url + '/airquality/points/', point).then(
              function (addedPoint) {
                _.remove(data.points, function (currentPoint) {
                  return currentPoint.id === point.id;
                });

                point.id = addedPoint.id;
                point.created = addedPoint.created;
                point.measurements = addedPoint.measurements;

                data.points.push(point);

                deferred.resolve(point);
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var now = new Date();

        if (!_.isString(point.id) || point.id.indexOf('x') === -1) {
          var id = 'x';

          if (!_.isEmpty(data.unsynced.points)) {
            id += parseInt(data.unsynced.points[data.unsynced.points.length - 1].id.replace('x', ''), 10) + 1;
          } else {
            id += 1;
          }

          point.id = id;
          point.created = now.toISOString();
          point.measurements = [];
          data.points.push(point);
        }

        viewport.calling = false;
        deferred.resolve(point);
      }
    );

    return deferred.promise;
  };

  api.deletePoint = function (pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(pointId)) {
      throw new Error('Point ID not specified');
    }

    viewport.calling = true;

    if (!_.isEmpty(data.point) && data.point.id === pointId) {
      delete data.point;
      state.redirect('points');
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.delete(url + '/airquality/points/' + pointId).then(
              function () {
                _.remove(data.points, function (currentPoint) {
                  return currentPoint.id === pointId;
                });

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var unsyncedPoint = _.find(data.unsynced.points, function (currentPoint) {
          return currentPoint.id === pointId;
        });

        if (unsyncedPoint) {
          _.remove(data.points, function (currentPoint) {
            return currentPoint.id === pointId;
          });
        } else {
          var point = _.find(data.points, function (currentPoint) {
            return currentPoint.id === pointId;
          });

          point.deleted = true;
        }

        viewport.calling = false;
        deferred.resolve();
      }
    );

    return deferred.promise;
  };

  api.startMeasurement = function (measurement, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurement)) {
      throw new Error('Measurement not specified');
    } else if (!_.isPlainObject(measurement)) {
      throw new Error('Measurement must be plain object');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.post(url + '/airquality/points/' + pointId + '/measurements/', measurement).then(
              function (addedMeasurement) {
                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurement.id;
                });

                measurement.id = addedMeasurement.id;
                measurement.created = addedMeasurement.created;

                point.measurements.push(measurement);

                deferred.resolve(measurement);
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var now = new Date();

        if (!_.isString(measurement.id) || measurement.id.indexOf('x') === -1) {
          var id = 'x';

          var newUnsyncedMeasurements = _.filter(point.measurements, function (currentMeasurement) {
            return _.isString(currentMeasurement.id) && currentMeasurement.id.indexOf('x') !== -1;
          });

          if (!_.isEmpty(newUnsyncedMeasurements)) {
            id += parseInt(newUnsyncedMeasurements[newUnsyncedMeasurements.length - 1].id.replace('x', ''), 10) + 1;
          } else {
            id += 1;
          }

          measurement.id = id;
          measurement.started = now.toISOString();
          point.measurements.push(measurement);
        }

        viewport.calling = false;
        deferred.resolve(measurement);
      }
    );

    return deferred.promise;
  };

  api.updateMeasurement = function (measurement, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurement)) {
      throw new Error('Measurement not specified');
    } else if (!_.isPlainObject(measurement)) {
      throw new Error('Measurement must be plain object');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    var now = new Date();

    if (measurement.finish && !measurement.finished) {
      measurement.finished = now.toISOString();
    }

    if (measurement.submit) {
      measurement.finish = false;

      if (!measurement.finished) {
        measurement.finished = now.toISOString();
      }
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.patch(url + '/airquality/points/' + pointId + '/measurements/' + measurement.id, measurement).then(
              function (updatedMeasurement) {
                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurement.id;
                });

                if (!measurement.submit) {
                  point.measurements.push(updatedMeasurement);
                }

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        measurement.updated = true;

        viewport.calling = false;
        deferred.resolve(measurement);
      }
    );

    return deferred.promise;
  };

  api.removeMeasurement = function (measurementId, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurementId)) {
      throw new Error('Measurement ID not specified');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.delete(url + '/airquality/points/' + pointId + '/measurements/' + measurementId).then(
              function () {
                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurementId;
                });

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (_.isString(measurementId) && measurementId.indexOf('x') > -1) {
          _.remove(point.measurements, function (currentPoint) {
            return currentPoint.id === measurementId;
          });
        } else {
          var measurement = _.find(point.measurements, function (currentMeasurement) {
            return currentMeasurement.id === measurementId;
          });

          measurement.deleted = true;
        }

        viewport.calling = false;
        deferred.resolve();
      }
    );

    return deferred.promise;
  };

  api.getProjects = function () {
    var deferred = $q.defer();
    var projects = storage.get('PROJECTS');

    viewport.calling = true;

    data.projects = [];

    if (!_.isEmpty(projects)) {
      projects = JSON.parse(projects);
    } else {
      projects = undefined;
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.get(url + '/airquality/projects/').then(
              function (retrievedProjects) {
                data.projects = retrievedProjects.data;
                deferred.resolve(data.projects);
              },
              function (error) {
                if (projects) {
                  data.projects = projects;
                }

                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (projects) {
          data.projects = projects;
        }

        viewport.calling = false;
        deferred.resolve(data.projects);
      }
    );

    return deferred.promise;
  };

  return api;
});
<commit_msg>Fixed API data results<commit_after>'use strict';

CMAQ.factory('api', function ($window, $q, $http, config, data, viewport, storage, state, oauth) {
  var api = {};
  var url = config.url + '/api';

  var unsynced = {
    points: []
  };

  api.online = function () {
    var deferred = $q.defer();

    $http.get('//' + $window.location.hostname).then(
      function () {
        viewport.offline = false;
        deferred.resolve();
      },
      function () {
        viewport.offline = true;
        deferred.reject();
      }
    );

    return deferred.promise;
  };

  api.sync = function () {
    var deferred = $q.defer();
    var totalPoints = 0;

    function resolve(index, total) {
      if (index + 1 === total) {
        unsynced.points = [];
        deferred.resolve();
      }
    }

    function syncMeasurements(point, pointIndex, totalPoints) {
      var total = 0;

      if (!_.isEmpty(point.measurements)) {
        total += point.measurements.length;

        _.each(point.measurements, function (measurement, index) {
          if (measurement.deleted) {
            api.removeMeasurement(measurement.id, point.id).finally(function () {
              if (index + 1 === total) {
                resolve(pointIndex, totalPoints);
              }
            });
          } else {
            if ((_.isString(measurement.id) && measurement.id.indexOf('x') > -1)) {
              api.startMeasurement(measurement, point.id).finally(function () {
                if (index + 1 === total) {
                  resolve(pointIndex, totalPoints);
                }
              });
            } else if (measurement.updated) {
              api.updatedMeasurement(measurement, point.id).finally(function () {
                if (index + 1 === total) {
                  resolve(pointIndex, totalPoints);
                }
              });
            }
          }
        });
      } else {
        resolve(pointIndex, totalPoints);
      }
    }

    if (_.isEmpty(unsynced.points)) {
      if (!_.isEmpty(data.unsynced.points)) {
        unsynced.points = _.cloneDeep(data.unsynced.points);
        totalPoints += unsynced.points.length;

        _.each(_.cloneDeep(unsynced.points), function (point, pointIndex) {
          if (point.deleted) {
            api.deletePoint(point.id).finally(function () {
              resolve(pointIndex, totalPoints);
            });
          } else {
            if ((_.isString(point.id) && point.id.indexOf('x') > -1)) {
              api.addPoint(point).then(
                function (addedPoint) {
                  point.id = addedPoint.id;
                  syncMeasurements(point, pointIndex, totalPoints);
                },
                function () {
                  resolve(pointIndex, totalPoints);
                }
              );
            }
          }
        });
      } else {
        deferred.resolve();
      }
    } else {
      deferred.resolve();
    }

    return deferred.promise;
  };

  api.getPoints = function () {
    var deferred = $q.defer();
    var points = storage.get('POINTS');

    viewport.calling = true;

    data.points = [];

    if (!_.isEmpty(points)) {
      points = JSON.parse(points);
    } else {
      points = undefined;
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.get(url + '/airquality/points/').then(
              function (retrievedPoints) {
                data.points = retrievedPoints.data;
                deferred.resolve(data.points);
              },
              function (error) {
                if (points) {
                  data.points = points;
                }

                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (points) {
          data.points = points;
        }

        viewport.calling = false;
        deferred.resolve(data.points);
      }
    );

    return deferred.promise;
  };

  api.addPoint = function (point) {
    var deferred = $q.defer();

    if (_.isUndefined(point)) {
      throw new Error('Point not specified');
    } else if (!_.isPlainObject(point)) {
      throw new Error('Point must be plain object');
    }

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.post(url + '/airquality/points/', point).then(
              function (addedPoint) {
                addedPoint = addedPoint.data;

                _.remove(data.points, function (currentPoint) {
                  return currentPoint.id === point.id;
                });

                point.id = addedPoint.id;
                point.created = addedPoint.created;
                point.measurements = addedPoint.measurements;

                data.points.push(point);

                deferred.resolve(point);
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var now = new Date();

        if (!_.isString(point.id) || point.id.indexOf('x') === -1) {
          var id = 'x';

          if (!_.isEmpty(data.unsynced.points)) {
            id += parseInt(data.unsynced.points[data.unsynced.points.length - 1].id.replace('x', ''), 10) + 1;
          } else {
            id += 1;
          }

          point.id = id;
          point.created = now.toISOString();
          point.measurements = [];
          data.points.push(point);
        }

        viewport.calling = false;
        deferred.resolve(point);
      }
    );

    return deferred.promise;
  };

  api.deletePoint = function (pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(pointId)) {
      throw new Error('Point ID not specified');
    }

    viewport.calling = true;

    if (!_.isEmpty(data.point) && data.point.id === pointId) {
      delete data.point;
      state.redirect('points');
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.delete(url + '/airquality/points/' + pointId).then(
              function () {
                _.remove(data.points, function (currentPoint) {
                  return currentPoint.id === pointId;
                });

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var unsyncedPoint = _.find(data.unsynced.points, function (currentPoint) {
          return currentPoint.id === pointId;
        });

        if (unsyncedPoint) {
          _.remove(data.points, function (currentPoint) {
            return currentPoint.id === pointId;
          });
        } else {
          var point = _.find(data.points, function (currentPoint) {
            return currentPoint.id === pointId;
          });

          point.deleted = true;
        }

        viewport.calling = false;
        deferred.resolve();
      }
    );

    return deferred.promise;
  };

  api.startMeasurement = function (measurement, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurement)) {
      throw new Error('Measurement not specified');
    } else if (!_.isPlainObject(measurement)) {
      throw new Error('Measurement must be plain object');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.post(url + '/airquality/points/' + pointId + '/measurements/', measurement).then(
              function (addedMeasurement) {
                addedMeasurement = addedMeasurement.data;

                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurement.id;
                });

                measurement.id = addedMeasurement.id;
                measurement.created = addedMeasurement.created;

                point.measurements.push(measurement);

                deferred.resolve(measurement);
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        var now = new Date();

        if (!_.isString(measurement.id) || measurement.id.indexOf('x') === -1) {
          var id = 'x';

          var newUnsyncedMeasurements = _.filter(point.measurements, function (currentMeasurement) {
            return _.isString(currentMeasurement.id) && currentMeasurement.id.indexOf('x') !== -1;
          });

          if (!_.isEmpty(newUnsyncedMeasurements)) {
            id += parseInt(newUnsyncedMeasurements[newUnsyncedMeasurements.length - 1].id.replace('x', ''), 10) + 1;
          } else {
            id += 1;
          }

          measurement.id = id;
          measurement.started = now.toISOString();
          point.measurements.push(measurement);
        }

        viewport.calling = false;
        deferred.resolve(measurement);
      }
    );

    return deferred.promise;
  };

  api.updateMeasurement = function (measurement, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurement)) {
      throw new Error('Measurement not specified');
    } else if (!_.isPlainObject(measurement)) {
      throw new Error('Measurement must be plain object');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    var now = new Date();

    if (measurement.finish && !measurement.finished) {
      measurement.finished = now.toISOString();
    }

    if (measurement.submit) {
      measurement.finish = false;

      if (!measurement.finished) {
        measurement.finished = now.toISOString();
      }
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.patch(url + '/airquality/points/' + pointId + '/measurements/' + measurement.id, measurement).then(
              function (updatedMeasurement) {
                updatedMeasurement = updatedMeasurement.data;

                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurement.id;
                });

                if (!measurement.submit) {
                  point.measurements.push(updatedMeasurement);
                }

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        measurement.updated = true;

        viewport.calling = false;
        deferred.resolve(measurement);
      }
    );

    return deferred.promise;
  };

  api.removeMeasurement = function (measurementId, pointId) {
    var deferred = $q.defer();

    if (_.isUndefined(measurementId)) {
      throw new Error('Measurement ID not specified');
    } else if (_.isUndefined(pointId)) {
      if (_.isUndefined(data.point)) {
        throw new Error('Point not set');
      } else if (!_.isPlainObject(data.point)) {
        throw new Error('Point must be plain object');
      }

      pointId = data.point.id;
    }

    var point = _.find(data.points, function (currentPoint) {
      return currentPoint.id === pointId;
    });

    viewport.calling = true;

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.delete(url + '/airquality/points/' + pointId + '/measurements/' + measurementId).then(
              function () {
                _.remove(point.measurements, function (currentMeasurement) {
                  return currentMeasurement.id === measurementId;
                });

                deferred.resolve();
              },
              function (error) {
                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (_.isString(measurementId) && measurementId.indexOf('x') > -1) {
          _.remove(point.measurements, function (currentPoint) {
            return currentPoint.id === measurementId;
          });
        } else {
          var measurement = _.find(point.measurements, function (currentMeasurement) {
            return currentMeasurement.id === measurementId;
          });

          measurement.deleted = true;
        }

        viewport.calling = false;
        deferred.resolve();
      }
    );

    return deferred.promise;
  };

  api.getProjects = function () {
    var deferred = $q.defer();
    var projects = storage.get('PROJECTS');

    viewport.calling = true;

    data.projects = [];

    if (!_.isEmpty(projects)) {
      projects = JSON.parse(projects);
    } else {
      projects = undefined;
    }

    api.online().then(
      function () {
        api.sync().finally(function () {
          oauth.refresh().finally(function () {
            $http.get(url + '/airquality/projects/').then(
              function (retrievedProjects) {
                data.projects = retrievedProjects.data;
                deferred.resolve(data.projects);
              },
              function (error) {
                if (projects) {
                  data.projects = projects;
                }

                deferred.reject(error);
              }
            ).finally(function () {
              viewport.calling = false;
            });
          });
        });
      },
      function () {
        if (projects) {
          data.projects = projects;
        }

        viewport.calling = false;
        deferred.resolve(data.projects);
      }
    );

    return deferred.promise;
  };

  return api;
});
<|endoftext|>


<commit_before>'use strict';

const environment = process.env.NODE_ENV || 'development';
const config = require('./config/config')({ environment });

const app = require('./config/express.config')({ config });

const User = require('./models/user.model')({});
const ItemListing = require('./models/item-listing.model')({});

const userData = require('./data/user.data')({ User });
const itemListingData = require('./data/item-listing.data')({ ItemListing });

const userController = require('./controllers/user.controller')({ userData, config });
const itemListingController = require('./controllers/item-listing.controller')({ itemListingData });
const favoritesController = require('./controllers/favorites.controller')({ userData, itemListingData });
const uploadController = require('./controllers/upload.controller')({});

require('./config/local.passport.config')({ app, userData });
require('./config/jwt.passport.config')({ app, userData, config });

require('./config/routes.config')({ app, userController, itemListingController, favoritesController, uploadController });

require('./config/mongoose.config')({ config });

app.listen(config.port, function () {
    console.log(`App listening on port: ${config.port}`);
});
<commit_msg>app.js: controller passed to router<commit_after>'use strict';

const environment = process.env.NODE_ENV || 'development';
const config = require('./config/config')({ environment });

const app = require('./config/express.config')({ config });

const User = require('./models/user.model')({});
const ItemListing = require('./models/item-listing.model')({});

const userData = require('./data/user.data')({ User });
const itemListingData = require('./data/item-listing.data')({ ItemListing });

const userController = require('./controllers/user.controller')({ userData, config });
const itemListingController = require('./controllers/item-listing.controller')({ itemListingData });
const favoritesController = require('./controllers/favorites.controller')({ userData, itemListingData });
const statistcsController = require('./controllers/statistics.controller')({ userData, itemListingData });
const uploadController = require('./controllers/upload.controller')({});

require('./config/local.passport.config')({ app, userData });
require('./config/jwt.passport.config')({ app, userData, config });

require('./config/routes.config')({ app, userController, itemListingController, favoritesController, uploadController, statistcsController });

require('./config/mongoose.config')({ config });

app.listen(config.port, function () {
    console.log(`App listening on port: ${config.port}`);
});
<|endoftext|>


<commit_before>// Name  : channeldata.js
// Author: Cerek Hillen
//
// Description:
//   Querying a channel for its current-user and message information. Options
//   allow one to define if it should return user information, message
//   information, and a number of different queries against messages.

/////////////
// Imports //
var sockethelper = require('../sockets/helper.js'),
    database     = require('../database.js');

//////////
// Code //

// Getting the current set of users for a given channel (and calling the
// callback) with theie value.
function getUsers(req, callback) {
    sockethelper.getChannelUsers(req.query.channel, function (users) {
        callback(null, users);
    });
}

// Constructing the database query for the set of messages from a given channel.
function constructMessageQuery(req, callback) {
    var query = {};

    query.channel = req.query.channel;

    // TODO: Do some other stuff too.

    callback(null, query);
}

// Getting the set of messages from a given server request.
function getMessages(req, callback) {
    constructMessageQuery(req, function (err, query) {
        if (err)
            return callback(err, []);

        database.schema.Message.find(query, function (err, messages) {
            if (err)
                return callback(err, []);

            callback(null, messages);
        });
    });
}

// Handling a GET request on this API endpoint.
function get(req, res) {
    if (req.query.channel === undefined) {
        return res.json({
            error  : true,
            success: false,
            message: 'You must provide a channel name to this API endpoint.'
        });
    }

    var fns = [],
        n   = 0;

    // Getting the users if necessary.
    if (req.query.users === undefined || req.query.users === 'true') {
        console.log(':)');
        fns.push(function (data, callback) {
            getUsers(req, function (err, users) {
                if (err)
                    callback(err, data);

                data.users = users;

                callback(null, data);
            });
        });
    }

    // Getting the messages if necessary.
    if (req.query.messages === undefined || req.query.messages === 'true') {
        fns.push(function (data, callback) {
            getMessages(req, function (err, messages) {
                if (err)
                    callback(err, data);

                data.messages = messages;

                callback(null, data);
            });
        });
    }

    // Adding the function to publish channel info.
    fns.push(function (data, callback) {
        res.json({
            error  : false,
            success: JSON.stringify(data) !== '{}',
            message: JSON.stringify(data) === '{}' ? 'You didn\'t request any data.' : 'Successfully retrieved channel data.',
            data   : data
        });
    });

    // Iterating through the functions in the
    var caller = function (err, data) {
        if (err) {
            return res.json({
                error  : err,
                success: false,
                message: 'Failed to construct channel data response: ' + String(err)
            });
        }

        fns[n++](data, caller);
    };

    caller(null, {});
}

/////////////
// Exports //
module.exports.path = '/channel/data';
module.exports.get = get;
<commit_msg>Made the voodoo feel a little less like voodoo.<commit_after>// Name  : channeldata.js
// Author: Cerek Hillen
//
// Description:
//   Querying a channel for its current-user and message information. Options
//   allow one to define if it should return user information, message
//   information, and a number of different queries against messages.

/////////////
// Imports //
var sockethelper = require('../sockets/helper.js'),
    database     = require('../database.js');

//////////
// Code //

// Getting the current set of users for a given channel (and calling the
// callback) with theie value.
function getUsers(req, callback) {
    sockethelper.getChannelUsers(req.query.channel, function (users) {
        callback(null, users);
    });
}

// Constructing the database query for the set of messages from a given channel.
function constructMessageQuery(req, callback) {
    var query = {};

    query.channel = req.query.channel;

    // TODO: Do some other stuff too.

    callback(null, query);
}

// Getting the set of messages from a given server request.
function getMessages(req, callback) {
    constructMessageQuery(req, function (err, query) {
        if (err)
            return callback(err, []);

        database.schema.Message.find(query, function (err, messages) {
            if (err)
                return callback(err, []);

            callback(null, messages);
        });
    });
}

// Handling a GET request on this API endpoint.
function get(req, res) {
    if (req.query.channel === undefined) {
        return res.json({
            error  : true,
            success: false,
            message: 'You must provide a channel name to this API endpoint.'
        });
    }

    var fns = [],
        n   = 0;

    if (req.query.users    === undefined || req.query.users    === 'true')
        fns.push({ fn: getUsers, name: 'users' });
    if (req.query.messages === undefined || req.query.messages === 'true')
        fns.push({ fn: getMessages, name: 'messages' });

    var caller = function (data) {
        if (n == fns.length) {
            return res.json({
                error  : false,
                success: JSON.stringify(data) !== '{}',
                message: JSON.stringify(data) === '{}' ? 'You didn\'t request any data.' : 'Successfully retrieved channel data.',
                data   : data
            });
        }

        fns[n].fn(req, function (err, rData) {
            data[fns[n].name] = rData;
            n++;

            caller(data);
        });
    };

    caller({});
}

/////////////
// Exports //
module.exports.path = '/channel/data';
module.exports.get = get;
<|endoftext|>


<commit_before>var _ = require('underscore');
var express = require('express');
var request = require('request');
var handlebars = require('handlebars');
var hbs = require('hbs');
var sendgrid = require('sendgrid');

var app = express();

app.configure('development', function() {
	app.use(express.bodyParser());
	app.use(express.errorHandler());
	app.locals.pretty = true;

	app.set("view engine", 'hbs');
	app.set("view options", { layout: false });

	app.engine('tmpl', require('hbs').__express);

	app.use(express.static(__dirname + '/public'));
});

app.get('/', function(req, res){
	if(req.query.token){
		//show page with selection of groups
		//maybe should be client-side js for loading the groups?
	} else {
		//send them a facebook auth screen - this could be done on the client side, too
	}
	res.send(__dirname + '/public/index.html');
});

app.get('/selection', function(req, res){
	if(req.query.token && req.query.fbid){
		request({json: true, url:'https://graph.facebook.com/me', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var user_info = body;
				request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						res.render('pages', {
							name: user_info.first_name,
							accessToken: req.query.token,
							pages: body.data
						}, function(err, html){
							res.send(html);
						});
					}
				});
			}
		});
	} else {
		res.redirect(__dirname + '/public/index.html');
	}
});

app.get('/:pageid', function(req, res){

});

app.get('/:pageid/:postid', function(req, res){

});

app.listen(80);<commit_msg>this is a thing<commit_after>var _ = require('underscore');
var express = require('express');
var request = require('request');
var handlebars = require('handlebars');
var hbs = require('hbs');
var sendgrid = require('sendgrid');

var app = express();

app.configure('development', function() {
	app.use(express.bodyParser());
	app.use(express.errorHandler());
	app.locals.pretty = true;

	app.set("view engine", 'hbs');
	app.set("view options", { layout: false });

	app.engine('tmpl', require('hbs').__express);

	app.use(express.static(__dirname + '/public'));
});

app.get('/', function(req, res){
	if(req.query.token){
		//show page with selection of groups
		//maybe should be client-side js for loading the groups?
	} else {
		//send them a facebook auth screen - this could be done on the client side, too
	}
	res.send(__dirname + '/public/index.html');
});

app.get('/selection', function(req, res){
	if(req.query.token && req.query.fbid){
		request({json: true, url:'https://graph.facebook.com/me', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var user_info = body;
				request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						res.send('this is a thing.');
						res.render('pages', {
							name: user_info.first_name,
							accessToken: req.query.token,
							pages: body.data
						}, function(err, html){
							res.send(html);
						});
					}
				});
			}
		});
	} else {
		res.redirect(__dirname + '/public/index.html');
	}
});

app.get('/:pageid', function(req, res){

});

app.get('/:pageid/:postid', function(req, res){

});

app.listen(80);<|endoftext|>