<commit_before>angular.module('admin').controller ('eventController', ['$scope', 'ngTableParams', '$http', '$timeout',
	function($scope, ngTableParams, $http, $timeout) {
		$scope.events = [];

		$http.get('/events/enumerateAll').success(function(data) {
			$scope.events = data;
		});

	  	$scope.tableParams = new ngTableParams({
        	page: 1,
			count: 10,
        	}, {
        	getData: function($defer, params) {
				$defer.resolve($scope.events.slice((params.page() - 1) * params.count(), params.page() * params.count()));
        	}
        });

        $scope.$watch('events', function() {
			$scope.tableParams.reload();
		});

        $scope.addEvent = function (newEvent) {
        	newEvent.start_date = new Date(newEvent.start_date);
        	newEvent.end_date = new Date(newEvent.end_date);
        	$http.post('/events/create',newEvent).success(function() {
        		console.log('Event created');
        		$scope.events.push(newEvent);
        	})
        	$scope.newEvent = null;
  		};

		$scope.deleteEvent = function(event) {
			$http.post('/events/delete',{event_id:event._id}).success(function() {
				console.log('Event Deleted');
			});
		};

  		//the following code sets up the date selectors in the event form
  		$scope.today = function() {
			$scope.dt = new Date();
		}
		$scope.today();

		$scope.clear = function() {
			$scope.dt = null;
		}

		$scope.openS = function($event) {
			$event.preventDefault();
			$event.stopPropagation();
			$scope.openedS = true;
		}

		$scope.openE = function($event) {
			$event.preventDefault();
			$event.stopPropagation();
			$scope.openedE = true;
		}

		$scope.dateOptions = {
			formatYear: 'yy',
			startingDay: 1
		};
	}
]);

<commit_msg>fixed bug with the event creation in the events ctrl<commit_after>angular.module('admin').controller ('eventController', ['$scope', 'ngTableParams', '$http', '$timeout',
	function($scope, ngTableParams, $http, $timeout) {
		$scope.events = [];

		$http.get('/events/enumerateAll').success(function(data) {
			$scope.events = data;
		});

	  	$scope.tableParams = new ngTableParams({
        	page: 1,
			count: 10,
        	}, {
        	getData: function($defer, params) {
				$defer.resolve($scope.events.slice((params.page() - 1) * params.count(), params.page() * params.count()));
        	}
        });

        $scope.$watch('events', function() {
			$scope.tableParams.reload();
		});

        $scope.addEvent = function (newEvent) {
        	newEvent.start_date = new Date(newEvent.start_date).getTime();
        	newEvent.end_date = new Date(newEvent.end_date).getTime();
        	$http.post('/events/create',newEvent).success(function() {
        		console.log('Event created');
        		$scope.events.push(newEvent);
        	})
        	$scope.newEvent = null;
  		};

		$scope.deleteEvent = function(event) {
			$http.post('/events/delete',{event_id:event._id}).success(function() {
				console.log('Event Deleted');
			});
		};

  		//the following code sets up the date selectors in the event form
  		$scope.today = function() {
			$scope.dt = new Date();
		}
		$scope.today();

		$scope.clear = function() {
			$scope.dt = null;
		}

		$scope.openS = function($event) {
			$event.preventDefault();
			$event.stopPropagation();
			$scope.openedS = true;
		}

		$scope.openE = function($event) {
			$event.preventDefault();
			$event.stopPropagation();
			$scope.openedE = true;
		}

		$scope.dateOptions = {
			formatYear: 'yy',
			startingDay: 1
		};
	}
]);

<|endoftext|>


<commit_before>"use strict";
/*
* Bokeh background generator
* to use:
* var background = new boke( [max number of bokeh circles], [your div id] )
*/
; var bokeh = function(maxCircles,elId){
	this.generatedCircles = [],
	this.mouse = {
		Px : 0,
		Py : 0,
		Nx : 0,
		Ny : 0,
		distance: 0,
		velocity: 0
	};

	var canvas = document.getElementById(elId),
		maxCircleSize = Math.floor(window.innerWidth/6);

	canvas.style.width = window.innerWidth + "px";
	canvas.style.height = window.innerHeight + "px";
	canvas.style.overflow = "hidden";
	canvas.style.position = "relative";

	while( canvas.hasChildNodes() ){
		canvas.removeChild(canvas.lastChild);
	}

	var self = this,
		max = maxCircles,
		loop = function(){
			for(var i = 0; i<max; i++){
				self.createRandomCircles(canvas, (window.innerHeight - maxCircleSize), (window.innerWidth - maxCircleSize), maxCircleSize);
			}
		};

	loop();
};

bokeh.prototype.createRandomCircles = function(cv,cx,cy,max){
	var self = this,
		root = 3,
		x = Math.floor(Math.random() * cx),
		y = Math.floor(Math.random() * cy),
		r = (Math.floor(Math.random() * max)) * 2,
		color = "rgba("+Math.floor(Math.random() * 255)+","+Math.floor(Math.random() * 255)+","+Math.floor(Math.random() * 255)+", "+ Math.random() +")",
		opacity = Math.random();

	var d = document.createElement('div');
	d.style.width = r + "px";
	d.style.height = r + "px";
	d.style.position = "absolute";
	d.style.borderRadius = "50%";
	d.style.top = x + "px";
	d.style.left = y + "px";
	d.style.border = Math.round(Math.pow(r, 1/root)) + "px solid " + color;
	d.style.background = color;
	d.style.opacity = opacity;
	d.style.boxShadow = "0 0 " + Math.round(Math.pow(r, 1/root)) * 2 + "px " + color + ", inset 0 0 " + Math.round(Math.pow(r, 1/root)) + "px " + color;

	self.generatedCircles.push(d);
	cv.appendChild(d);
};<commit_msg>changed container attribute to absolute<commit_after>"use strict";
/*
* Bokeh background generator
* to use:
* var background = new boke( [max number of bokeh circles], [your div id] )
*/
; var bokeh = function(maxCircles,elId){
	this.generatedCircles = [],
	this.mouse = {
		Px : 0,
		Py : 0,
		Nx : 0,
		Ny : 0,
		distance: 0,
		velocity: 0
	};

	var canvas = document.getElementById(elId),
		maxCircleSize = Math.floor(window.innerWidth/6);

	canvas.style.width = window.innerWidth + "px";
	canvas.style.height = window.innerHeight + "px";
	canvas.style.overflow = "hidden";
	canvas.style.position = "absolute";

	while( canvas.hasChildNodes() ){
		canvas.removeChild(canvas.lastChild);
	}

	var self = this,
		max = maxCircles,
		loop = function(){
			for(var i = 0; i<max; i++){
				self.createRandomCircles(canvas, (window.innerHeight - maxCircleSize), (window.innerWidth - maxCircleSize), maxCircleSize);
			}
		};

	loop();
};

bokeh.prototype.createRandomCircles = function(cv,cx,cy,max){
	var self = this,
		root = 3,
		x = Math.floor(Math.random() * cx),
		y = Math.floor(Math.random() * cy),
		r = (Math.floor(Math.random() * max)) * 2,
		color = "rgba("+Math.floor(Math.random() * 255)+","+Math.floor(Math.random() * 255)+","+Math.floor(Math.random() * 255)+", "+ Math.random() +")",
		opacity = Math.random();

	var d = document.createElement('div');
	d.style.width = r + "px";
	d.style.height = r + "px";
	d.style.position = "absolute";
	d.style.borderRadius = "50%";
	d.style.top = x + "px";
	d.style.left = y + "px";
	d.style.border = Math.round(Math.pow(r, 1/root)) + "px solid " + color;
	d.style.background = color;
	d.style.opacity = opacity;
	d.style.boxShadow = "0 0 " + Math.round(Math.pow(r, 1/root)) * 2 + "px " + color + ", inset 0 0 " + Math.round(Math.pow(r, 1/root)) + "px " + color;

	self.generatedCircles.push(d);
	cv.appendChild(d);
};<|endoftext|>


<commit_before>var Botkit = require('botkit');
var nag = require('./nag');
var controller;
var bot;

/**
 * Start the bot
 *
 * @returns {Object} the created slackbot
 */
exports.start = function start() {
    controller = Botkit.slackbot({
        debug: process.env.NODE_ENV !== 'production',
        storage: require('botkit-storage-mongo')({mongoUri: process.env.DATABASE_URL})
    });

    bot = controller.spawn({
        token: process.env.SLACKBOT_TOKEN_HEMERA
    }).startRTM();

    // Keep their slack profile up to date for every message
    controller.on('message_received', require('./updateSlackProfile'));

    // Setup our message listeners
    controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', require('./listeners/hi'));
    controller.hears(['help'], 'direct_message,direct_mention,mention', require('./listeners/help'));
    controller.hears(['snooze (.*)'], 'direct_message,direct_mention,mention', require('./listeners/snooze'));
    controller.hears(['snooze'], 'direct_message,direct_mention,mention', require('./listeners/snoozeOops'));
    controller.hears(['subscribe (.*)'], 'direct_message,direct_mention,mention', require('./listeners/subscribe'));
    controller.hears(['subscribe'], 'direct_message,direct_mention,mention', require('./listeners/subscribeOops'));
    controller.hears(['list'], 'direct_message,direct_mention,mention', require('./listeners/list'));
    controller.hears(['show (.*)'], 'direct_message,direct_mention,mention', require('./listeners/show'));
    controller.hears(['show'], 'direct_message,direct_mention,mention', require('./listeners/showOops'));
    controller.hears(['reset'], 'direct_message,direct_mention,mention', require('./listeners/reset'));

    // Nag people about posting updates every hour
    setInterval(nag, 1000 * 60 * 60);
    nag();

    return bot;
};

/**
 * Get the botkit controller
 * @return {Object}
 */
exports.getController = function getController() {
    return controller;
}

/**
 * Get the running bot
 * @return {Object}
 */
exports.getBot = function getController() {
    return bot;
}
<commit_msg>Use utility method<commit_after>var Botkit = require('botkit');
var nag = require('./nag');
var controller;
var bot;

/**
 * Start the bot
 *
 * @returns {Object} the created slackbot
 */
exports.start = function start() {
    controller = Botkit.slackbot({
        debug: process.env.NODE_ENV !== 'production',
        storage: require('botkit-storage-mongo')({mongoUri: process.env.DATABASE_URL})
    });

    bot = controller.spawn({
        token: process.env.SLACKBOT_TOKEN_HEMERA
    }).startRTM();

    // Keep their slack profile up to date for every message
    controller.on('message_received', require('../utils/updateSlackProfile'));

    // Setup our message listeners
    controller.hears(['hello', 'hi'], 'direct_message,direct_mention,mention', require('./listeners/hi'));
    controller.hears(['help'], 'direct_message,direct_mention,mention', require('./listeners/help'));
    controller.hears(['snooze (.*)'], 'direct_message,direct_mention,mention', require('./listeners/snooze'));
    controller.hears(['snooze'], 'direct_message,direct_mention,mention', require('./listeners/snoozeOops'));
    controller.hears(['subscribe (.*)'], 'direct_message,direct_mention,mention', require('./listeners/subscribe'));
    controller.hears(['subscribe'], 'direct_message,direct_mention,mention', require('./listeners/subscribeOops'));
    controller.hears(['list'], 'direct_message,direct_mention,mention', require('./listeners/list'));
    controller.hears(['show (.*)'], 'direct_message,direct_mention,mention', require('./listeners/show'));
    controller.hears(['show'], 'direct_message,direct_mention,mention', require('./listeners/showOops'));
    controller.hears(['reset'], 'direct_message,direct_mention,mention', require('./listeners/reset'));

    // Nag people about posting updates every hour
    nag();
    setInterval(nag, 1000 * 5);
    //setInterval(nag, 1000 * 60 * 60);

    return bot;
};

/**
 * Get the botkit controller
 * @return {Object}
 */
exports.getController = function getController() {
    return controller;
}

/**
 * Get the running bot
 * @return {Object}
 */
exports.getBot = function getController() {
    return bot;
}
<|endoftext|>


<commit_before>function pageViewModel(gvm) {
    gvm.projecttitle = ko.observable("");
    gvm.userId = -1;
    gvm.coupledCount = 0;

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.addmoduleBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Addmodule");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.getProjectInfo = function() {
        $.getJSON('/api/project/' + $("#projectHeader").data('value'), function(data) {
            gvm.pageHeader(data[0].code + ' - ' + data[0].name);
        });
    };

    gvm.coupledLists = ko.observableArray([]);
    gvm.availableLists = ko.observableArray([]);

    gvm.addCoupledList = function(id, name) {
        // Push data
        var tblOject = {tid: id, tname: name};
        gvm.coupledLists.push(tblOject);

        $("#uncouplebtn-" + id).click(function(){
            showYesNoModal("Bent u zeker dat u dit item wil ontkoppelen?", function(val){
                if(val){
                    $.ajax({
                        url: '/api/project/' + $("#projectHeader").data('value') +'/studentlist/uncouple/' + id,
                        type: "DELETE",
                        success: function() {
                            gvm.coupledCount--;
                            viewModel.coupledLists.remove(tblOject);
                        }
                    });

                }
            });
        });
    }

    gvm.addAvailableLists = function(id, name) {
        var tblOject = {tid: id, tname: name};
        gvm.availableLists.push(tblOject);

        $("#couplebtn-" + id).click(function(){
            if(gvm.coupledCount == 0) {
                $.ajax({
                    url: '/api/project/' + $("#projectHeader").data('value') + '/studentlist/' + id,
                    type: "POST",
                    success: function() {
                        gvm.coupledCount++;
                        viewModel.coupledLists.push(tblOject);
                    }
                });
            } else {
                alert("list already coupled");
            }
        });
    }

    gvm.getCoupledLists = function() {
        $.getJSON('/api/project/' + $("#projectHeader").data('value') + '/coupledlists', function(data) {
            $.each(data, function(i, item) {
                gvm.coupledCount++;
                gvm.addCoupledList(item.id, item.name);
            });
        });
    }

    gvm.getAvailableLists = function() {
        $.getJSON('/api/studentlists/' + gvm.userId, function(data) {
            $.each(data, function(i, item) {
                gvm.addAvailableLists(item.id, item.name);
            });
        });
    }
 }

 function getAllTeachers() {
     var teachers = [];
     $.getJSON('/api/getteacherrapport', function(data) {
        $.each(data, function(i, item) {
            teachers.push(item.firstname + " " + item.lastname);
        });
    });
    return teachers;
 }

 function addTeacher(event, serialData) {
     console.log(serialData);
     /*$.ajax({
            url: "/api/addcourseteacher",
            type: "POST",
            data: serialData,
            success: function(data) {
                //show teacher in list
            },
            error: function(data) {
                console.log('Failed to add teacher');
            }
    });*/
     event.preventDefault();
 }

function initPage() {
    viewModel.getProjectInfo();
    viewModel.getCoupledLists();

    //Add Teacher

    $('#addTeacherForm').hide();

    $('#addTeacher').click(function(){
        $("#addTeacherForm").show();
        $('#teachersComplete').autocomplete({ source: getAllTeachers() });
    });

    $('#addTeacherBtn').click(function() {
        console.log($('#addTeacherForm').serialize());
        addTeacher($('#addTeacherForm').serialize());
        $('#addTeacherForm').hide();
    });

    //Add StudentList

    $('#addStudentListForm').hide();

    $('#addStudentList').click(function(){
        $("#addStudentListForm").show();
        //$('#teachersComplete').autocomplete({ source: getAllTeachers() });
    });

    $('#addStudentListBtn').click(function() {
        $('#addStudentListForm').hide();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.getAvailableLists(data.id);
    });
}
<commit_msg>teachers kunnen toevoegen adhv autocomplete<commit_after>function pageViewModel(gvm) {
    gvm.projecttitle = ko.observable("");
    gvm.userId = -1;
    gvm.coupledCount = 0;

    // Page specific i18n bindings
    gvm.title = ko.computed(function (){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("ProjectTitle") + ": " + gvm.projecttitle();}, gvm);
    gvm.pageHeader = ko.observable("Project");
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.addmoduleBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("Addmodule");}, gvm);
    gvm.savePage = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SaveBtn");}, gvm);

    gvm.getProjectInfo = function() {
        $.getJSON('/api/project/' + $("#projectHeader").data('value'), function(data) {
            gvm.pageHeader(data[0].code + ' - ' + data[0].name);
        });
    };

    gvm.coupledLists = ko.observableArray([]);
    gvm.availableLists = ko.observableArray([]);

    gvm.addCoupledList = function(id, name) {
        // Push data
        var tblOject = {tid: id, tname: name};
        gvm.coupledLists.push(tblOject);

        $("#uncouplebtn-" + id).click(function(){
            showYesNoModal("Bent u zeker dat u dit item wil ontkoppelen?", function(val){
                if(val){
                    $.ajax({
                        url: '/api/project/' + $("#projectHeader").data('value') +'/studentlist/uncouple/' + id,
                        type: "DELETE",
                        success: function() {
                            gvm.coupledCount--;
                            viewModel.coupledLists.remove(tblOject);
                        }
                    });

                }
            });
        });
    }

    gvm.addAvailableLists = function(id, name) {
        var tblOject = {tid: id, tname: name};
        gvm.availableLists.push(tblOject);

        $("#couplebtn-" + id).click(function(){
            if(gvm.coupledCount == 0) {
                $.ajax({
                    url: '/api/project/' + $("#projectHeader").data('value') + '/studentlist/' + id,
                    type: "POST",
                    success: function() {
                        gvm.coupledCount++;
                        viewModel.coupledLists.push(tblOject);
                    }
                });
            } else {
                alert("list already coupled");
            }
        });
    }

    gvm.getCoupledLists = function() {
        $.getJSON('/api/project/' + $("#projectHeader").data('value') + '/coupledlists', function(data) {
            $.each(data, function(i, item) {
                gvm.coupledCount++;
                gvm.addCoupledList(item.id, item.name);
            });
        });
    }

    gvm.getAvailableLists = function() {
        $.getJSON('/api/studentlists/' + gvm.userId, function(data) {
            $.each(data, function(i, item) {
                gvm.addAvailableLists(item.id, item.name);
            });
        });
    }
 }

 function getAllTeachers() {
     var teachers = [];
     $.getJSON('/api/getteacherrapport', function(data) {
        $.each(data, function(i, item) {
            teachers.push(item.firstname + " " + item.lastname);
        });
    });
    return teachers;
 }

 function addTeacher(event, serialData) {
     $.ajax({
            url: "/api/addcourseteacher",
            type: "POST",
            data: serialData,
            success: function(data) {
                //show teacher in list
            },
            error: function(data) {
                console.log('Failed to add teacher');
            }
    });
     event.preventDefault();   //to stay on the same page
 }

function initPage() {
    viewModel.getProjectInfo();
    viewModel.getCoupledLists();

    //Add Teacher

    $('#addTeacherForm').hide();

    $('#addTeacher').click(function(){
        $("#addTeacherForm").show();
        $('#teachersComplete').autocomplete({ source: getAllTeachers() });
    });

    $('#addTeacherBtn').click(function() {
        addTeacher($('#addTeacherForm').serialize());
        $('#addTeacherForm').hide();
    });

    //Add StudentList

    $('#addStudentListForm').hide();

    $('#addStudentList').click(function(){
        $("#addStudentListForm").show();
        //$('#teachersComplete').autocomplete({ source: getAllTeachers() });
    });

    $('#addStudentListBtn').click(function() {
        $('#addStudentListForm').hide();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.getAvailableLists(data.id);
    });
}
<|endoftext|>


<commit_before>/*globals module exports resource require BObject BArray DOMParser console*/
/*jslint undef: true, strict: true, white: true, newcap: true, browser: true, indent: 4 */
"use strict";

var util = require('util'),
    path = require('path'),
    ccp = require('geometry').ccp,
    base64 = require('base64'),
    gzip   = require('gzip'),
    TMXOrientationOrtho = require('./TMXOrientation').TMXOrientationOrtho,
    TMXOrientationHex = require('./TMXOrientation').TMXOrientationHex,
    TMXOrientationIso = require('./TMXOrientation').TMXOrientationIso;

var TMXTilesetInfo = BObject.extend(/** @lends cocos.TMXTilesetInfo# */{
    name: '',
    firstGID: 0,
    tileSize: null,
    spacing: 0,
    margin: 0,
    sourceImage: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXTilesetInfo.superclass.init.call(this);
    },

    rectForGID: function (gid) {
        var rect = {size: {}, origin: ccp(0, 0)};
        rect.size = util.copy(this.tileSize);

        gid = gid - this.firstGID;

        var imgSize = this.get('imageSize');

        var maxX = Math.floor((imgSize.width - this.margin * 2 + this.spacing) / (this.tileSize.width + this.spacing));

        rect.origin.x = (gid % maxX) * (this.tileSize.width + this.spacing) + this.margin;
        rect.origin.y = Math.floor(gid / maxX) * (this.tileSize.height + this.spacing) + this.margin;

        return rect;
    }
});

var TMXLayerInfo = BObject.extend(/** @lends cocos.TMXLayerInfo# */{
    name: '',
    layerSize: null,
    tiles: null,
    visible: true,
    opacity: 255,
    minGID: 100000,
    maxGID: 0,
    properties: null,
    offset: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXLayerInfo.superclass.init.call(this);

        this.properties = {};
        this.offset = ccp(0, 0);
    }
});

var TMXObjectGroup = BObject.extend(/** @lends cocos.TMXObjectGroup# */{
    name: '',
    properties: null,
    offset: null,
    objects: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXObjectGroup.superclass.init.call(this);

        this.properties = {};
        this.objects = {};
        this.offset = ccp(0, 0);
    },

    /**
     * Get the value for the specific property name
     *
     * @opt {String} name Property name
     * @returns {String} Property value
     */
    getProperty: function (opts) {
        var propertyName = opts.name;
        return this.properties[propertyName];
    },

    /**
     * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty
     */
    propertyNamed: function (opts) {
        console.warn('TMXObjectGroup#propertyNamed is deprected. Use TMXTiledMap#getProperty instread');
        return this.getProperty(opts);
    },

    /**
     * Get the object for the specific object name. It will return the 1st
     * object found on the array for the given name.
     *
     * @opt {String} name Object name
     * @returns {Object} Object
     */
    getObject: function (opts) {
        var objectName = opts.name;
        var object = null;

        this.objects.forEach(function (item) {
            if (item.name == objectName) {
                object = item;
            }
        });
        if (object !== null) {
            return object;
        }
    },

    /**
     * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty
     */
    objectNamed: function (opts) {
        console.warn('TMXObjectGroup#objectNamed is deprected. Use TMXObjectGroup#getObject instread');
        return this.getObject(opts);
    }
});

var TMXMapInfo = BObject.extend(/** @lends cocos.TMXMapInfo# */{
    filename: '',
    orientation: 0,
    mapSize: null,
    tileSize: null,
    layer: null,
    tilesets: null,
    objectGroups: null,
    properties: null,
    tileProperties: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     *
     * @param {String} tmxFile The file path of the TMX file to load
     */
    init: function (tmxFile) {
        TMXMapInfo.superclass.init.call(this, tmxFile);

        this.tilesets = [];
        this.layers = [];
        this.objectGroups = [];
        this.properties = {};
        this.tileProperties = {};
        this.filename = tmxFile;

        this.parseXMLFile(tmxFile);
    },

    parseXMLFile: function (xmlFile) {
        var parser = new DOMParser(),
            doc = parser.parseFromString(resource(xmlFile), 'text/xml');

        // PARSE <map>
        var map = doc.documentElement;

        // Set Orientation
        switch (map.getAttribute('orientation')) {
        case 'orthogonal':
            this.orientation = TMXOrientationOrtho;
            break;
        case 'isometric':
            this.orientation = TMXOrientationIso;
            break;
        case 'hexagonal':
            this.orientation = TMXOrientationHex;
            break;
        default:
            throw "cocos2d: TMXFomat: Unsupported orientation: " + map.getAttribute('orientation');
        }
        this.mapSize = {width: parseInt(map.getAttribute('width'), 10), height: parseInt(map.getAttribute('height'), 10)};
        this.tileSize = {width: parseInt(map.getAttribute('tilewidth'), 10), height: parseInt(map.getAttribute('tileheight'), 10)};

        // PARSE <tilesets>
        var tilesets = map.getElementsByTagName('tileset');
        var i, j, len, jen, s;
        for (i = 0, len = tilesets.length; i < len; i++) {
            var t = tilesets[i];

            var tileset = TMXTilesetInfo.create();
            tileset.set('name', t.getAttribute('name'));
            tileset.set('firstGID', parseInt(t.getAttribute('firstgid'), 10));
            if (t.getAttribute('spacing')) {
                tileset.set('spacing', parseInt(t.getAttribute('spacing'), 10));
            }
            if (t.getAttribute('margin')) {
                tileset.set('margin', parseInt(t.getAttribute('margin'), 10));
            }

            s = {};
            s.width = parseInt(t.getAttribute('tilewidth'), 10);
            s.height = parseInt(t.getAttribute('tileheight'), 10);
            tileset.set('tileSize', s);

            // PARSE <image> We assume there's only 1
            var image = t.getElementsByTagName('image')[0];
            tileset.set('sourceImage', path.join(path.dirname(this.filename), image.getAttribute('source')));

            this.tilesets.push(tileset);
        }

        // PARSE <layers>
        var layers = map.getElementsByTagName('layer');
        for (i = 0, len = layers.length; i < len; i++) {
            var l = layers[i];
            var data = l.getElementsByTagName('data')[0];
            var layer = TMXLayerInfo.create();

            layer.set('name', l.getAttribute('name'));
            if (l.getAttribute('visible') !== false) {
                layer.set('visible', true);
            } else {
                layer.set('visible', !!parseInt(l.getAttribute('visible'), 10));
            }

            s = {};
            s.width = parseInt(l.getAttribute('width'), 10);
            s.height = parseInt(l.getAttribute('height'), 10);
            layer.set('layerSize', s);

            var opacity = l.getAttribute('opacity');
            if (opacity === undefined) {
                layer.set('opacity', 255);
            } else {
                layer.set('opacity', 255 * parseFloat(opacity));
            }

            var x = parseInt(l.getAttribute('x'), 10),
                y = parseInt(l.getAttribute('y'), 10);
            if (isNaN(x)) {
                x = 0;
            }
            if (isNaN(y)) {
                y = 0;
            }
            layer.set('offset', ccp(x, y));

            // Firefox has a 4KB limit on node values. It will split larger
            // nodes up into multiple nodes. So, we'll stitch them back
            // together.
            var nodeValue = '';
            for (j = 0, jen = data.childNodes.length; j < jen; j++) {
                nodeValue += data.childNodes[j].nodeValue;
            }

            // Unpack the tilemap data
            var compression = data.getAttribute('compression');
            switch (compression) {
            case 'gzip':
                layer.set('tiles', gzip.unzipBase64AsArray(nodeValue, 4));
                break;

            // Uncompressed
            case null:
            case '':
                layer.set('tiles', base64.decodeAsArray(nodeValue, 4));
                break;

            default:
                throw "Unsupported TMX Tile Map compression: " + compression;
            }

            this.layers.push(layer);
        }

        // TODO PARSE <tile>

        // PARSE <objectgroup>
        var objectgroups = map.getElementsByTagName('objectgroup');
        for (i = 0, len = objectgroups.length; i < len; i++) {
            var g = objectgroups[i],
                objectGroup = TMXObjectGroup.create();

            objectGroup.set('name', g.getAttribute('name'));

            var properties = g.querySelectorAll('objectgroup > properties property'),
                propertiesValue = {},
                property;

            for (j = 0; j < properties.length; j++) {
                property = properties[j];
                if (property.getAttribute('name')) {
                    propertiesValue[property.getAttribute('name')] = property.getAttribute('value');
                }
            }

            objectGroup.set('properties', propertiesValue);

            var objectsArray = [],
                objects = g.querySelectorAll('object');

            for (j = 0; j < objects.length; j++) {
                var object = objects[j];
                var objectValue = {
                    x       : parseInt(object.getAttribute('x'), 10),
                    y       : parseInt(object.getAttribute('y'), 10),
                    width   : parseInt(object.getAttribute('width'), 10),
                    height  : parseInt(object.getAttribute('height'), 10)
                };
                if (object.getAttribute('name')) {
                    objectValue.name = object.getAttribute('name');
                }
                if (object.getAttribute('type')) {
                    objectValue.name = object.getAttribute('type');
                }
                properties = object.querySelectorAll('property');
                for (var k = 0; k < properties.length; k++) {
                    property = properties[k];
                    if (property.getAttribute('name')) {
                        objectValue[property.getAttribute('name')] = property.getAttribute('value');
                    }
                }
                objectsArray.push(objectValue);

            }
            objectGroup.set('objects', objectsArray);
            this.objectGroups.push(objectGroup);
        }
    }
});

exports.TMXMapInfo = TMXMapInfo;
exports.TMXLayerInfo = TMXLayerInfo;
exports.TMXTilesetInfo = TMXTilesetInfo;
exports.TMXObjectGroup = TMXObjectGroup;
<commit_msg>fixed object type<commit_after>/*globals module exports resource require BObject BArray DOMParser console*/
/*jslint undef: true, strict: true, white: true, newcap: true, browser: true, indent: 4 */
"use strict";

var util = require('util'),
    path = require('path'),
    ccp = require('geometry').ccp,
    base64 = require('base64'),
    gzip   = require('gzip'),
    TMXOrientationOrtho = require('./TMXOrientation').TMXOrientationOrtho,
    TMXOrientationHex = require('./TMXOrientation').TMXOrientationHex,
    TMXOrientationIso = require('./TMXOrientation').TMXOrientationIso;

var TMXTilesetInfo = BObject.extend(/** @lends cocos.TMXTilesetInfo# */{
    name: '',
    firstGID: 0,
    tileSize: null,
    spacing: 0,
    margin: 0,
    sourceImage: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXTilesetInfo.superclass.init.call(this);
    },

    rectForGID: function (gid) {
        var rect = {size: {}, origin: ccp(0, 0)};
        rect.size = util.copy(this.tileSize);

        gid = gid - this.firstGID;

        var imgSize = this.get('imageSize');

        var maxX = Math.floor((imgSize.width - this.margin * 2 + this.spacing) / (this.tileSize.width + this.spacing));

        rect.origin.x = (gid % maxX) * (this.tileSize.width + this.spacing) + this.margin;
        rect.origin.y = Math.floor(gid / maxX) * (this.tileSize.height + this.spacing) + this.margin;

        return rect;
    }
});

var TMXLayerInfo = BObject.extend(/** @lends cocos.TMXLayerInfo# */{
    name: '',
    layerSize: null,
    tiles: null,
    visible: true,
    opacity: 255,
    minGID: 100000,
    maxGID: 0,
    properties: null,
    offset: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXLayerInfo.superclass.init.call(this);

        this.properties = {};
        this.offset = ccp(0, 0);
    }
});

var TMXObjectGroup = BObject.extend(/** @lends cocos.TMXObjectGroup# */{
    name: '',
    properties: null,
    offset: null,
    objects: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     */
    init: function () {
        TMXObjectGroup.superclass.init.call(this);

        this.properties = {};
        this.objects = {};
        this.offset = ccp(0, 0);
    },

    /**
     * Get the value for the specific property name
     *
     * @opt {String} name Property name
     * @returns {String} Property value
     */
    getProperty: function (opts) {
        var propertyName = opts.name;
        return this.properties[propertyName];
    },

    /**
     * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty
     */
    propertyNamed: function (opts) {
        console.warn('TMXObjectGroup#propertyNamed is deprected. Use TMXTiledMap#getProperty instread');
        return this.getProperty(opts);
    },

    /**
     * Get the object for the specific object name. It will return the 1st
     * object found on the array for the given name.
     *
     * @opt {String} name Object name
     * @returns {Object} Object
     */
    getObject: function (opts) {
        var objectName = opts.name;
        var object = null;

        this.objects.forEach(function (item) {
            if (item.name == objectName) {
                object = item;
            }
        });
        if (object !== null) {
            return object;
        }
    },

    /**
     * @deprected Since v0.2. You should now use cocos.TMXObjectGroup#getProperty
     */
    objectNamed: function (opts) {
        console.warn('TMXObjectGroup#objectNamed is deprected. Use TMXObjectGroup#getObject instread');
        return this.getObject(opts);
    }
});

var TMXMapInfo = BObject.extend(/** @lends cocos.TMXMapInfo# */{
    filename: '',
    orientation: 0,
    mapSize: null,
    tileSize: null,
    layer: null,
    tilesets: null,
    objectGroups: null,
    properties: null,
    tileProperties: null,

    /**
     * @memberOf cocos
     * @constructs
     * @extends BObject
     *
     * @param {String} tmxFile The file path of the TMX file to load
     */
    init: function (tmxFile) {
        TMXMapInfo.superclass.init.call(this, tmxFile);

        this.tilesets = [];
        this.layers = [];
        this.objectGroups = [];
        this.properties = {};
        this.tileProperties = {};
        this.filename = tmxFile;

        this.parseXMLFile(tmxFile);
    },

    parseXMLFile: function (xmlFile) {
        var parser = new DOMParser(),
            doc = parser.parseFromString(resource(xmlFile), 'text/xml');

        // PARSE <map>
        var map = doc.documentElement;

        // Set Orientation
        switch (map.getAttribute('orientation')) {
        case 'orthogonal':
            this.orientation = TMXOrientationOrtho;
            break;
        case 'isometric':
            this.orientation = TMXOrientationIso;
            break;
        case 'hexagonal':
            this.orientation = TMXOrientationHex;
            break;
        default:
            throw "cocos2d: TMXFomat: Unsupported orientation: " + map.getAttribute('orientation');
        }
        this.mapSize = {width: parseInt(map.getAttribute('width'), 10), height: parseInt(map.getAttribute('height'), 10)};
        this.tileSize = {width: parseInt(map.getAttribute('tilewidth'), 10), height: parseInt(map.getAttribute('tileheight'), 10)};

        // PARSE <tilesets>
        var tilesets = map.getElementsByTagName('tileset');
        var i, j, len, jen, s;
        for (i = 0, len = tilesets.length; i < len; i++) {
            var t = tilesets[i];

            var tileset = TMXTilesetInfo.create();
            tileset.set('name', t.getAttribute('name'));
            tileset.set('firstGID', parseInt(t.getAttribute('firstgid'), 10));
            if (t.getAttribute('spacing')) {
                tileset.set('spacing', parseInt(t.getAttribute('spacing'), 10));
            }
            if (t.getAttribute('margin')) {
                tileset.set('margin', parseInt(t.getAttribute('margin'), 10));
            }

            s = {};
            s.width = parseInt(t.getAttribute('tilewidth'), 10);
            s.height = parseInt(t.getAttribute('tileheight'), 10);
            tileset.set('tileSize', s);

            // PARSE <image> We assume there's only 1
            var image = t.getElementsByTagName('image')[0];
            tileset.set('sourceImage', path.join(path.dirname(this.filename), image.getAttribute('source')));

            this.tilesets.push(tileset);
        }

        // PARSE <layers>
        var layers = map.getElementsByTagName('layer');
        for (i = 0, len = layers.length; i < len; i++) {
            var l = layers[i];
            var data = l.getElementsByTagName('data')[0];
            var layer = TMXLayerInfo.create();

            layer.set('name', l.getAttribute('name'));
            if (l.getAttribute('visible') !== false) {
                layer.set('visible', true);
            } else {
                layer.set('visible', !!parseInt(l.getAttribute('visible'), 10));
            }

            s = {};
            s.width = parseInt(l.getAttribute('width'), 10);
            s.height = parseInt(l.getAttribute('height'), 10);
            layer.set('layerSize', s);

            var opacity = l.getAttribute('opacity');
            if (opacity === undefined) {
                layer.set('opacity', 255);
            } else {
                layer.set('opacity', 255 * parseFloat(opacity));
            }

            var x = parseInt(l.getAttribute('x'), 10),
                y = parseInt(l.getAttribute('y'), 10);
            if (isNaN(x)) {
                x = 0;
            }
            if (isNaN(y)) {
                y = 0;
            }
            layer.set('offset', ccp(x, y));

            // Firefox has a 4KB limit on node values. It will split larger
            // nodes up into multiple nodes. So, we'll stitch them back
            // together.
            var nodeValue = '';
            for (j = 0, jen = data.childNodes.length; j < jen; j++) {
                nodeValue += data.childNodes[j].nodeValue;
            }

            // Unpack the tilemap data
            var compression = data.getAttribute('compression');
            switch (compression) {
            case 'gzip':
                layer.set('tiles', gzip.unzipBase64AsArray(nodeValue, 4));
                break;

            // Uncompressed
            case null:
            case '':
                layer.set('tiles', base64.decodeAsArray(nodeValue, 4));
                break;

            default:
                throw "Unsupported TMX Tile Map compression: " + compression;
            }

            this.layers.push(layer);
        }

        // TODO PARSE <tile>

        // PARSE <objectgroup>
        var objectgroups = map.getElementsByTagName('objectgroup');
        for (i = 0, len = objectgroups.length; i < len; i++) {
            var g = objectgroups[i],
                objectGroup = TMXObjectGroup.create();

            objectGroup.set('name', g.getAttribute('name'));

            var properties = g.querySelectorAll('objectgroup > properties property'),
                propertiesValue = {},
                property;

            for (j = 0; j < properties.length; j++) {
                property = properties[j];
                if (property.getAttribute('name')) {
                    propertiesValue[property.getAttribute('name')] = property.getAttribute('value');
                }
            }

            objectGroup.set('properties', propertiesValue);

            var objectsArray = [],
                objects = g.querySelectorAll('object');

            for (j = 0; j < objects.length; j++) {
                var object = objects[j];
                var objectValue = {
                    x       : parseInt(object.getAttribute('x'), 10),
                    y       : parseInt(object.getAttribute('y'), 10),
                    width   : parseInt(object.getAttribute('width'), 10),
                    height  : parseInt(object.getAttribute('height'), 10)
                };
                if (object.getAttribute('name')) {
                    objectValue.name = object.getAttribute('name');
                }
                if (object.getAttribute('type')) {
                    objectValue.type = object.getAttribute('type');
                }
                properties = object.querySelectorAll('property');
                for (var k = 0; k < properties.length; k++) {
                    property = properties[k];
                    if (property.getAttribute('name')) {
                        objectValue[property.getAttribute('name')] = property.getAttribute('value');
                    }
                }
                objectsArray.push(objectValue);

            }
            objectGroup.set('objects', objectsArray);
            this.objectGroups.push(objectGroup);
        }
    }
});

exports.TMXMapInfo = TMXMapInfo;
exports.TMXLayerInfo = TMXLayerInfo;
exports.TMXTilesetInfo = TMXTilesetInfo;
exports.TMXObjectGroup = TMXObjectGroup;
<|endoftext|>


<commit_before>var _ = require('lodash');
var marked = require('marked');

var renderer = require('./renderer');

// Split a page up into sections (lesson, exercises, ...)
function splitSections(nodes) {
    var section = [];

    return _.reduce(nodes, function(sections, el) {
        if(el.type === 'hr') {
            sections.push(section);
            section = [];
        } else {
            section.push(el);
        }

        return sections;
    }, []).concat([section]); // Add remaining nodes
}

// What is the type of this section
function sectionType(nodes, idx) {
    var codeNodes = _.filter(nodes, {
        type: 'code'
    }).length;

    if(codeNodes === 3 && (idx % 2) == 1) {
        return 'exercise';
    }

    return 'normal';
}

// Render a section using our custom renderer
function render(section) {
    // marked's Render expects this, we don't use it yet
    section.links = {};

    // Build options using defaults and our custom renderer
    var options = _.extend({}, marked.defaults, {
        renderer: renderer()
    });

    return marked.parser(section, options);
}

function parsePage(src) {
    var nodes = marked.lexer(src);

    return _.chain(splitSections(nodes))
    .map(function(section, idx) {
        // Detect section type
        section.type = sectionType(section, idx);
        return section;
    })
    .map(function(section) {
        // Transform given type
        if(section.type === 'exercise') {
            var nonCodeNodes = _.reject(section, {
                'type': 'code'
            });

            var codeNodes = _.filter(section, {
                'type': 'code'
            });

            return {
                type: section.type,
                content: render(nonCodeNodes),
                code: {
                    base: codeNodes[0].text,
                    solution: codeNodes[1].text,
                    validation: codeNodes[2].text,
                }
            };
        }

        // Render normal pages
        return {
            type: section.type,
            content: render(section)
        };
    })
    .value();
}

// Exports
module.exports = parsePage;
<commit_msg>Generate a unique Id for each section<commit_after>var _ = require('lodash');
var marked = require('marked');

var renderer = require('./renderer');

// Split a page up into sections (lesson, exercises, ...)
function splitSections(nodes) {
    var section = [];

    return _.reduce(nodes, function(sections, el) {
        if(el.type === 'hr') {
            sections.push(section);
            section = [];
        } else {
            section.push(el);
        }

        return sections;
    }, []).concat([section]); // Add remaining nodes
}

// What is the type of this section
function sectionType(nodes, idx) {
    var codeNodes = _.filter(nodes, {
        type: 'code'
    }).length;

    if(codeNodes === 3 && (idx % 2) == 1) {
        return 'exercise';
    }

    return 'normal';
}

// Render a section using our custom renderer
function render(section) {
    // marked's Render expects this, we don't use it yet
    section.links = {};

    // Build options using defaults and our custom renderer
    var options = _.extend({}, marked.defaults, {
        renderer: renderer()
    });

    return marked.parser(section, options);
}

function parsePage(src) {
    var nodes = marked.lexer(src);

    return _.chain(splitSections(nodes))
    .map(function(section, idx) {
        // Detect section type
        section.type = sectionType(section, idx);
        return section;
    })
    .map(function(section) {
        // Generate a uniqueId to identify this section in our code
        var id = _.uniqueId('gitbook_');

        // Transform given type
        if(section.type === 'exercise') {
            var nonCodeNodes = _.reject(section, {
                'type': 'code'
            });

            var codeNodes = _.filter(section, {
                'type': 'code'
            });

            return {
                id: id,
                type: section.type,
                content: render(nonCodeNodes),
                code: {
                    base: codeNodes[0].text,
                    solution: codeNodes[1].text,
                    validation: codeNodes[2].text,
                }
            };
        }

        // Render normal pages
        return {
            id: id,
            type: section.type,
            content: render(section)
        };
    })
    .value();
}

// Exports
module.exports = parsePage;
<|endoftext|>


<commit_before>const isTravis = process.env.TRAVIS;
const isSaucelabs = process.argv.indexOf('--saucelabs') !== -1 || (isTravis && process.env.TRAVIS_PULL_REQUEST === 'false');

if (isSaucelabs && !process.env.SAUCE_USERNAME) {
  try {
    const credentials = require('./saucelabs.json');
    process.env.SAUCE_USERNAME = credentials.username;
    process.env.SAUCE_ACCESS_KEY = credentials.accessKey;
  } catch (err) {
    console.log('Please, create a valid "saucelabs.json" with your credentials.');
    process.exit(1);
  }
}

module.exports = function(config) {
  const cfg = {
    basePath: '',

    frameworks: ['jasmine'],

    files: [
        // For travis
        'node_modules/es6-shim/es6-shim.js',
        // paths loaded by Karma
        {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: false},
        {pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: false},
        {pattern: 'node_modules/tether/dist/js/tether.min.js', included: true, watched: false},
        {pattern: 'karma-shim.js', included: true, watched: true},

        // paths loaded via module imports
        {pattern: 'temp/**/*.js', included: false, watched: true},

        // paths to support debugging with source maps in dev tools
        {pattern: 'src/**/*.ts', included: false, watched: false},
        {pattern: 'temp/**/*.js.map', included: false, watched: false},

        // fixtures
        {pattern: 'test/fixtures/**', watched: false, included: false, served: true},
    ],

    proxies: {
      '/assets/icons/utility-sprite/svg/symbols.svg': '/base/test/fixtures/fake.svg',
      '/tether': '/base/node_modules/tether/dist/js/tether.min.js'
    },

    preprocessors: {
      'temp/**/*.js': ['sourcemap'],
      'temp/src/**/!(*spec|*mock).js': ['coverage'],
    },

    coverageReporter: {
      dir: 'coverage/',
      reporters: [{type: 'text-summary'}, {type: 'html'}],
    },

    reporters: isTravis ? ['dots'] : ['progress', 'coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: [isTravis ? 'Firefox' : 'Chrome'],
    singleRun: false,
  };

  if (isSaucelabs) {
    cfg.customLaunchers =  require('./test/browser-providers');
    cfg.browsers = Object.keys(cfg.customLaunchers);
    cfg.reporters.push('saucelabs');
    cfg.sauceLabs = {
      tunnelIdentifier: isTravis ? process.env.TRAVIS_JOB_NUMBER : 'ng-lightning',
      connectOptions: {
        logfile: './saucelabs.log',
      },
    };
    cfg.captureTimeout = 120000;
    cfg.browserNoActivityTimeout = 120000;
  }

  config.set(cfg);
};
<commit_msg>chore(build): change local karma port<commit_after>const isTravis = process.env.TRAVIS;
const isSaucelabs = process.argv.indexOf('--saucelabs') !== -1 || (isTravis && process.env.TRAVIS_PULL_REQUEST === 'false');

if (isSaucelabs && !process.env.SAUCE_USERNAME) {
  try {
    const credentials = require('./saucelabs.json');
    process.env.SAUCE_USERNAME = credentials.username;
    process.env.SAUCE_ACCESS_KEY = credentials.accessKey;
  } catch (err) {
    console.log('Please, create a valid "saucelabs.json" with your credentials.');
    process.exit(1);
  }
}

module.exports = function(config) {
  const cfg = {
    basePath: '',

    frameworks: ['jasmine'],

    files: [
        // For travis
        'node_modules/es6-shim/es6-shim.js',
        // paths loaded by Karma
        {pattern: 'node_modules/systemjs/dist/system.src.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/angular2-polyfills.js', included: true, watched: false},
        {pattern: 'node_modules/rxjs/bundles/Rx.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/angular2.js', included: true, watched: false},
        {pattern: 'node_modules/angular2/bundles/testing.dev.js', included: true, watched: false},
        {pattern: 'node_modules/tether/dist/js/tether.min.js', included: true, watched: false},
        {pattern: 'karma-shim.js', included: true, watched: true},

        // paths loaded via module imports
        {pattern: 'temp/**/*.js', included: false, watched: true},

        // paths to support debugging with source maps in dev tools
        {pattern: 'src/**/*.ts', included: false, watched: false},
        {pattern: 'temp/**/*.js.map', included: false, watched: false},

        // fixtures
        {pattern: 'test/fixtures/**', watched: false, included: false, served: true},
    ],

    proxies: {
      '/assets/icons/utility-sprite/svg/symbols.svg': '/base/test/fixtures/fake.svg',
      '/tether': '/base/node_modules/tether/dist/js/tether.min.js'
    },

    preprocessors: {
      'temp/**/*.js': ['sourcemap'],
      'temp/src/**/!(*spec|*mock).js': ['coverage'],
    },

    coverageReporter: {
      dir: 'coverage/',
      reporters: [{type: 'text-summary'}, {type: 'html'}],
    },

    reporters: isTravis ? ['dots'] : ['progress', 'coverage'],
    port: isTravis ? 9876 : 23011,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: [isTravis ? 'Firefox' : 'Chrome'],
    singleRun: false,
  };

  if (isSaucelabs) {
    cfg.customLaunchers =  require('./test/browser-providers');
    cfg.browsers = Object.keys(cfg.customLaunchers);
    cfg.reporters.push('saucelabs');
    cfg.sauceLabs = {
      tunnelIdentifier: isTravis ? process.env.TRAVIS_JOB_NUMBER : 'ng-lightning',
      connectOptions: {
        logfile: './saucelabs.log',
      },
    };
    cfg.captureTimeout = 120000;
    cfg.browserNoActivityTimeout = 120000;
  }

  config.set(cfg);
};
<|endoftext|>


<commit_before>export default {
  NAME: "advertisements",
};

//PUBLIC_URL replaced by path to public folder at build time
export const pathToAds = process.env.PUBLIC_URL + "/img/ads/";

export const adRedirects = [['kweller', "http://www.kwellerprep.com"],
                            ['aimplus', "http://www.aimpluseducation.com"],
                            ['kweller', "https://thetutorverse.com/stuy"]
                             ];
<commit_msg>whoopsie<commit_after>export default {
  NAME: "advertisements",
};

//PUBLIC_URL replaced by path to public folder at build time
export const pathToAds = process.env.PUBLIC_URL + "/img/ads/";

export const adRedirects = [['kweller', "http://www.kwellerprep.com"],
                            ['aimplus', "http://www.aimpluseducation.com"],
                            ['tutorverse', "https://thetutorverse.com/stuy"]
                             ];
<|endoftext|>


<commit_before>'use strict';

// Books controller
angular.module('books').controller('BooksController', ['$scope', '$timeout', '$stateParams', '$location', '$modal', '$log', '$translate', 'Authentication', 'Shelves', 'Genres',
	function($scope, $timeout, $stateParams, $location, $modal, $log, $translate, Authentication, Shelves, Genres) {
		$scope.authentication = Authentication;
		$scope.shelves = Shelves.query();
		$scope.genres = Genres.query();

		$scope.data = {
			shelves: [],
			alert: null
		};

		// Create new Book
		$scope.create = function(data) {
			Shelves.get({ shelfId: data.shelf._id }).$promise.then(function(shelf) {
				shelf.$createBook({
					isbn: data.isbn,
					title: data.title,
					author: data.author,
					publishedDate: data.publishedDate,
					description: data.description,
					pageCount: data.pageCount,
					thumbnail: data.thumbnail,
					coverColour: data.coverColour,
					fontColour: data.fontColour,
					genre: data.genre.name
				},
					function(response) {
						$scope.find();

						// TODO: service for alerts
						$translate('Book has been created.').then(function (alert) {
					    $scope.data.alert = alert;

					    $timeout(function() {
		            $scope.data.alert = null;
		          }, 3000);
					  });
					},
					function(errorResponse) {
						$scope.error = errorResponse.data.message;
					});
			});
		};

		// Remove existing Book
		$scope.remove = function(data) {
			data.shelf.$deleteBook({ 'bookId': data._id},
				function(response) {
					$scope.find();
					// TODO: service for alerts
					$translate('Book has been deleted.').then(function (alert) {
				    $scope.data.alert = alert;

				    $timeout(function() {
	            $scope.data.alert = null;
	          }, 3000);
				  });
				},
				function(errorResponse) {
					$scope.error = errorResponse.data.message;
			});
		};

		// Update existing Book
		$scope.update = function(data) {
			Shelves.get({ shelfId: data.shelf._id }).$promise.then(function(shelf) {

				// Get shelf for this book to check if it shelf hasnt changed
				Shelves.byBook({ bookId: data._id}).$promise.then(function(currentShelf) {
					if (shelf._id !== currentShelf[0]._id) {
						// Shelf has changed
						// Delete the book from the currentShelf
						var currentData = {};
						currentData = angular.copy(data);
						currentData.shelf = currentShelf[0];

						$scope.remove(currentData);

						// Create book in the shelf
						$scope.create(data);
					} else {
						shelf.$updateBook({ 'bookId': data._id,
							isbn: data.isbn,
							title: data.title,
							author: data.author,
							publishedDate: data.publishedDate,
							description: data.description,
							pageCount: data.pageCount,
							thumbnail: data.thumbnail,
							coverColour: data.coverColour,
							fontColour: data.fontColour,
							genre: data.genre
						},
						function(response) {
							$scope.find();

							// TODO: service for alerts
							$translate('Book has been updated.').then(function (alert) {
						    $scope.data.alert = alert;

						    $timeout(function() {
			            $scope.data.alert = null;
			          }, 3000);
						  });
						},
						function(errorResponse) {
							$scope.error = errorResponse.data.message;
						});
		      }
	      });
			});
		};

		// Find a list of Books
		$scope.find = function() {
			Shelves.query().$promise.then(function(shelves) {
      	$scope.data.shelves = shelves;
    	});
		};

		$scope.addShelf = function() {
			Shelves.save({}, {name: $scope.formData.newshelf}, function(response) {
				$scope.shelves = Shelves.query(function(shelf) {
					// Preselect shelf with newly created item
					$scope.formData.shelf = shelf[0];
				});
			}, function(errorResponse) {
				$scope.errorResponse = errorResponse.data.message;
			});
		};

		// $scope.addGenre = function() {
		// 	Genres.save({}, {name: $scope.formData.newgenre}, function(response) {
		// 		$scope.genres = Genres.query(function(genres) {
		// 			// Preselect genre with newly created item
		// 			$scope.formData.genre = genres[0];
		// 		});
		// 	}, function(errorResponse) {
		// 		$scope.errorResponse = errorResponse.data.message;
		// 	});
		// };

		$scope.modalUpdate = function (size, selectedBook) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/edit-book.client.view.html',
	      controller: function($scope, $modalInstance, book) {
	      	Shelves.byBook({ bookId: book._id}, function(shelf) {
	      		$scope.formData = book;
						$scope.formData.shelf = shelf[0];
	      	});

	      	$scope.ok = function () {
				    if (this.form.editBookForm.$valid) {
	      			$modalInstance.close($scope.formData);
      			} else {
      				$translate('Please fill or required fields').then(function (requiredFields) {
						    $scope.error = requiredFields;
						  });
      			}
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size,
	      resolve: {
	        book: function () {
	        	return selectedBook;
	        }
	      }
	    });

	    modalInstance.result.then(function (formData) {
	      $scope.update(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

	  $scope.modalDelete = function (size, selectedShelf, selectedBook) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/delete-book.client.view.html',
	      controller: function($scope, $modalInstance, book, shelf) {
	      	$scope.formData = book;
	      	$scope.formData.shelf = shelf;

	      	$scope.ok = function () {
				    $modalInstance.close($scope.formData);
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size,
	      resolve: {
	        book: function () {
	          return selectedBook;
	        },
	        shelf: function () {
	          return selectedShelf;
	        }
	      }
	    });

	    modalInstance.result.then(function (formData) {
	    	$scope.remove(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

		$scope.modalCreate = function (size) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/create-book.client.view.html',
	      controller: function($scope, $modalInstance) {
	      	$scope.formData = { };
	      	$scope.formData.fontColour = '#FFFFFF';
	      	$scope.formData.coverColour = '#000000';

	      	$scope.ok = function () {
	      		if (this.form.createBookForm.$valid) {
	      			$modalInstance.close($scope.formData);
      			} else {
      				$translate('Please fill or required fields').then(function (requiredFields) {
						    $scope.error = requiredFields;
						  });
      			}
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size
	    });

	    modalInstance.result.then(function (formData) {
    		$scope.create(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

	  // Load books
	  $scope.find();
	}
]);<commit_msg>add book genre<commit_after>'use strict';

// Books controller
angular.module('books').controller('BooksController', ['$scope', '$timeout', '$stateParams', '$location', '$modal', '$log', '$translate', 'Authentication', 'Shelves', 'Genres',
	function($scope, $timeout, $stateParams, $location, $modal, $log, $translate, Authentication, Shelves, Genres) {
		$scope.authentication = Authentication;
		$scope.shelves = Shelves.query();
		$scope.genres = Genres.query();

		$scope.data = {
			shelves: [],
			alert: null
		};

		// Create new Book
		$scope.create = function(data) {
			Shelves.get({ shelfId: data.shelf._id }).$promise.then(function(shelf) {
				shelf.$createBook({
					isbn: data.isbn,
					title: data.title,
					author: data.author,
					publishedDate: data.publishedDate,
					description: data.description,
					pageCount: data.pageCount,
					thumbnail: data.thumbnail,
					coverColour: data.coverColour,
					fontColour: data.fontColour,
					genre: data.genre.name
				},
					function(response) {
						$scope.find();

						// TODO: service for alerts
						$translate('Book has been created.').then(function (alert) {
					    $scope.data.alert = alert;

					    $timeout(function() {
		            $scope.data.alert = null;
		          }, 3000);
					  });
					},
					function(errorResponse) {
						$scope.error = errorResponse.data.message;
					});
			});
		};

		// Remove existing Book
		$scope.remove = function(data) {
			data.shelf.$deleteBook({ 'bookId': data._id},
				function(response) {
					$scope.find();
					// TODO: service for alerts
					$translate('Book has been deleted.').then(function (alert) {
				    $scope.data.alert = alert;

				    $timeout(function() {
	            $scope.data.alert = null;
	          }, 3000);
				  });
				},
				function(errorResponse) {
					$scope.error = errorResponse.data.message;
			});
		};

		// Update existing Book
		$scope.update = function(data) {
			Shelves.get({ shelfId: data.shelf._id }).$promise.then(function(shelf) {

				// Get shelf for this book to check if it shelf hasnt changed
				Shelves.byBook({ bookId: data._id}).$promise.then(function(currentShelf) {
					if (shelf._id !== currentShelf[0]._id) {
						// Shelf has changed
						// Delete the book from the currentShelf
						var currentData = {};
						currentData = angular.copy(data);
						currentData.shelf = currentShelf[0];

						$scope.remove(currentData);

						// Create book in the shelf
						$scope.create(data);
					} else {
						shelf.$updateBook({ 'bookId': data._id,
							isbn: data.isbn,
							title: data.title,
							author: data.author,
							publishedDate: data.publishedDate,
							description: data.description,
							pageCount: data.pageCount,
							thumbnail: data.thumbnail,
							coverColour: data.coverColour,
							fontColour: data.fontColour,
							genre: data.genre
						},
						function(response) {
							$scope.find();

							// TODO: service for alerts
							$translate('Book has been updated.').then(function (alert) {
						    $scope.data.alert = alert;

						    $timeout(function() {
			            $scope.data.alert = null;
			          }, 3000);
						  });
						},
						function(errorResponse) {
							$scope.error = errorResponse.data.message;
						});
		      }
	      });
			});
		};

		// Find a list of Books
		$scope.find = function() {
			Shelves.query().$promise.then(function(shelves) {
      	$scope.data.shelves = shelves;
    	});
		};

		$scope.addShelf = function() {
			Shelves.save({}, {name: $scope.formData.newshelf}, function(response) {
				$scope.shelves = Shelves.query(function(shelf) {
					// Preselect shelf with newly created item
					$scope.formData.shelf = shelf[0];
				});
			}, function(errorResponse) {
				$scope.errorResponse = errorResponse.data.message;
			});
		};

		$scope.addGenre = function() {
			Genres.save({}, {name: $scope.formData.newgenre}, function(response) {
				$scope.genres = Genres.query(function(genres) {
					// Preselect genre with newly created item
					$scope.formData.genre = genres[0];
				});
			}, function(errorResponse) {
				$scope.errorResponse = errorResponse.data.message;
			});
		};

		$scope.modalUpdate = function (size, selectedBook) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/edit-book.client.view.html',
	      controller: function($scope, $modalInstance, book) {
	      	Shelves.byBook({ bookId: book._id}, function(shelf) {
	      		$scope.formData = book;
						$scope.formData.shelf = shelf[0];
	      	});

	      	$scope.ok = function () {
				    if (this.form.editBookForm.$valid) {
	      			$modalInstance.close($scope.formData);
      			} else {
      				$translate('Please fill or required fields').then(function (requiredFields) {
						    $scope.error = requiredFields;
						  });
      			}
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size,
	      resolve: {
	        book: function () {
	        	return selectedBook;
	        }
	      }
	    });

	    modalInstance.result.then(function (formData) {
	      $scope.update(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

	  $scope.modalDelete = function (size, selectedShelf, selectedBook) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/delete-book.client.view.html',
	      controller: function($scope, $modalInstance, book, shelf) {
	      	$scope.formData = book;
	      	$scope.formData.shelf = shelf;

	      	$scope.ok = function () {
				    $modalInstance.close($scope.formData);
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size,
	      resolve: {
	        book: function () {
	          return selectedBook;
	        },
	        shelf: function () {
	          return selectedShelf;
	        }
	      }
	    });

	    modalInstance.result.then(function (formData) {
	    	$scope.remove(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

		$scope.modalCreate = function (size) {
	    var modalInstance = $modal.open({
	      templateUrl: 'modules/books/views/create-book.client.view.html',
	      controller: function($scope, $modalInstance) {
	      	$scope.formData = { };
	      	$scope.formData.fontColour = '#FFFFFF';
	      	$scope.formData.coverColour = '#000000';

	      	$scope.ok = function () {
	      		if (this.form.createBookForm.$valid) {
	      			$modalInstance.close($scope.formData);
      			} else {
      				$translate('Please fill or required fields').then(function (requiredFields) {
						    $scope.error = requiredFields;
						  });
      			}
				  };

				  $scope.cancel = function () {
				    $modalInstance.dismiss('cancel');
				  };
	      },
	      size: size
	    });

	    modalInstance.result.then(function (formData) {
    		$scope.create(formData);
	    }, function () {
	      $log.info('Modal dismissed at: ' + new Date());
	    });
	  };

	  // Load books
	  $scope.find();
	}
]);<|endoftext|>


<commit_before>/**
 * Created by Ushan on 3/19/2016.
 */
google.charts.load('current', {'packages': ['line']});
function drawChart() {
    console.log("draw")
    $.post("http://localhost/CW2_AWT_2012042/quiz/question/attempt", {},
        function (response) {
            if (response == 'error') {
                alert("please log in first!");
            } else {
                var jsonResponse =   JSON.parse(response)
                var data = new google.visualization.DataTable();
                data.addColumn('number', 'attempt');
                data.addColumn('number', 'Score');
                var graph_data = [];
                $.each(jsonResponse.user_progress , function (index, value) {
                    console.log('My array has at position ' + index + ', this value: ' + value["score"]);
                    graph_data.push([index * 1, value["score"] * 1])
                })
                ;
                console.log(graph_data);
                data.addRows(graph_data)
                var options = {
                    chart: {
                        title: 'Previous attempt score chart',
                        subtitle: ''
                    },
                    width: 900,
                    height: 500
                };

                var chart = new google.charts.Line(document.getElementById('chart_div'));

                chart.draw(data, options);
            }
        }
    );

}
<commit_msg>chnage graph size<commit_after>/**
 * Created by Ushan on 3/19/2016.
 */
google.charts.load('current', {'packages': ['line']});
function drawChart() {
    console.log("draw")
    $.post("http://localhost/CW2_AWT_2012042/quiz/question/attempt", {},
        function (response) {
            if (response == 'error') {
                alert("please log in first!");
            } else {
                var jsonResponse =   JSON.parse(response)
                var data = new google.visualization.DataTable();
                data.addColumn('number', 'attempt');
                data.addColumn('number', 'Score');
                var graph_data = [];
                $.each(jsonResponse.user_progress , function (index, value) {
                    graph_data.push([(index+1) * 1, value["score"] * 1])
                })
                ;
                console.log(graph_data);
                data.addRows(graph_data)
                var options = {
                    hAxis: {
                        title: 'Attempt',
                        min:0
                    },
                    vAxis: {
                        title: 'Score',
                        min:0
                    },
                    width: 600,
                    height: 250
                };

                var chart = new google.charts.Line(document.getElementById('chart_div'));

                chart.draw(data, options);
            }
        }
    );

}
<|endoftext|>


<commit_before>(function(window) {
	var HAS_HASHCHANGE = (function() {
		var doc_mode = window.documentMode;
		return ('onhashchange' in window) &&
			(doc_mode === undefined || doc_mode > 7);
	})();

	L.Hash = function(map) {
		this.onHashChange = L.Util.bind(this.onHashChange, this);

		if (map) {
			this.init(map);
		}
	};

	/** adapted to additionally parse region info from the hash
	 *  and to provide default values if parts of the hash are not present
	 */
	L.Hash.parseHash = function(hash) {
		if(hash.indexOf('#') === 0) {
			hash = hash.substr(1);
		}

		var parsed = {
			region: rkGlobal.defaultRegion,
			zoom: rkGlobal.defaultZoom,
			center: undefined
		}

		var args = hash.split("/");

		if(args.length >= 1) {
			var region = args[0];
			if(region in rkGlobal.configurations) {
				parsed.region = region;
			}
		}

		if(args.length >= 2) {
			var zoom = (L.version >= '1.0.0') ? parseFloat(args[1]) : parseInt(args[1], 10);
			if(!isNaN(zoom)) {
				parsed.zoom = zoom
			}
		}

		var lat = undefined;
		var lon = undefined;
		if (args.length >= 4) {
			var lat = parseFloat(args[2]);
			var lon = parseFloat(args[3]);
		}

		if (!isNaN(lat) && !isNaN(lon)) {
			parsed.center = new L.LatLng(lat, lon);
		} else {
			var config = rkGlobal.configurations[parsed.region];
			parsed.center = config.centerLatLng;
		}

		return parsed;
	};

	L.Hash.formatHash = function(map) {
		var center = map.getCenter(),
		    zoom = map.getZoom(),
		    precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));

		return "#" + [this.region,
			//(L.version >= '1.0.0') ? zoom.toFixed(precision) : zoom,
			zoom,
			center.lat.toFixed(precision),
			center.lng.toFixed(precision)
		].join("/");
	};

	L.Hash.prototype = {
		map: null,
		lastHash: null,
		region: undefined,

		parseHash: L.Hash.parseHash,
		formatHash: L.Hash.formatHash,

		init: function(map) {
			this.map = map;

			// reset the hash
			this.lastHash = null;
			this.onHashChange();

			if (!this.isListening) {
				this.startListening();
			}
		},

		removeFrom: function(map) {
			if (this.changeTimeout) {
				clearTimeout(this.changeTimeout);
			}

			if (this.isListening) {
				this.stopListening();
			}

			this.map = null;
		},

		onMapMove: function() {
			// bail if we're moving the map (updating from a hash),
			// or if the map is not yet loaded

			if (this.movingMap || !this.map._loaded) {
				return false;
			}

			this.autoSwitchRegionIfCloseEnough();

			var hash = this.formatHash(this.map);
			if (this.lastHash != hash) {
				location.replace(hash);
				this.lastHash = hash;
			}
		},

		autoSwitchRegionIfCloseEnough: function() {
			for(const key of Object.keys(rkGlobal.configurations)) {
				if(key === this.region) {
					continue;
				}
				var distanceM = this.map.getCenter().distanceTo(rkGlobal.configurations[key].centerLatLng);
				if(distanceM < rkGlobal.autoSwitchDistanceMeters) {
					updateRadlkarteRegion(key);
					this.region = key;
					console.log("auto-switching region to " + key + ", map center is only " + Math.round(distanceM) + "m away");
					return;
				}
			}
		},

		movingMap: false,
		update: function() {
			var hash = location.hash;
			if (hash === this.lastHash) {
				return;
			}
			var parsed = this.parseHash(hash);
			this.movingMap = true;
			if(this.region !== parsed.region) {
				// console.log('hash update got a new region, change from ' + this.region + ' to ' + parsed.region);
				updateRadlkarteRegion(parsed.region);
				this.region = parsed.region;
			}
			this.map.setView(parsed.center, parsed.zoom);
			this.movingMap = false;
		},

		// defer hash change updates every 100ms
		changeDefer: 100,
		changeTimeout: null,
		onHashChange: function() {
			// throttle calls to update() so that they only happen every
			// `changeDefer` ms
			if (!this.changeTimeout) {
				var that = this;
				this.changeTimeout = setTimeout(function() {
					that.update();
					that.changeTimeout = null;
				}, this.changeDefer);
			}
		},

		isListening: false,
		hashChangeInterval: null,
		startListening: function() {
			this.map.on("moveend", this.onMapMove, this);

			if (HAS_HASHCHANGE) {
				L.DomEvent.addListener(window, "hashchange", this.onHashChange);
			} else {
				clearInterval(this.hashChangeInterval);
				this.hashChangeInterval = setInterval(this.onHashChange, 50);
			}
			this.isListening = true;
		},

		stopListening: function() {
			this.map.off("moveend", this.onMapMove, this);

			if (HAS_HASHCHANGE) {
				L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
			} else {
				clearInterval(this.hashChangeInterval);
			}
			this.isListening = false;
		}
	};

	L.hash = function(map) {
		return new L.Hash(map);
	};

	L.Map.prototype.addHash = function() {
		this._hash = L.hash(this);
	};

	L.Map.prototype.removeHash = function() {
		this._hash.removeFrom();
	};
})(window);
<commit_msg>better autoSwitch function<commit_after>(function(window) {
	var HAS_HASHCHANGE = (function() {
		var doc_mode = window.documentMode;
		return ('onhashchange' in window) &&
			(doc_mode === undefined || doc_mode > 7);
	})();

	L.Hash = function(map) {
		this.onHashChange = L.Util.bind(this.onHashChange, this);

		if (map) {
			this.init(map);
		}
	};

	/** adapted to additionally parse region info from the hash
	 *  and to provide default values if parts of the hash are not present
	 */
	L.Hash.parseHash = function(hash) {
		if(hash.indexOf('#') === 0) {
			hash = hash.substr(1);
		}

		var parsed = {
			region: rkGlobal.defaultRegion,
			zoom: rkGlobal.defaultZoom,
			center: undefined
		}

		var args = hash.split("/");

		if(args.length >= 1) {
			var region = args[0];
			if(region in rkGlobal.configurations) {
				parsed.region = region;
			}
		}

		if(args.length >= 2) {
			var zoom = (L.version >= '1.0.0') ? parseFloat(args[1]) : parseInt(args[1], 10);
			if(!isNaN(zoom)) {
				parsed.zoom = zoom
			}
		}

		var lat = undefined;
		var lon = undefined;
		if (args.length >= 4) {
			var lat = parseFloat(args[2]);
			var lon = parseFloat(args[3]);
		}

		if (!isNaN(lat) && !isNaN(lon)) {
			parsed.center = new L.LatLng(lat, lon);
		} else {
			var config = rkGlobal.configurations[parsed.region];
			parsed.center = config.centerLatLng;
		}

		return parsed;
	};

	L.Hash.formatHash = function(map) {
		var center = map.getCenter(),
		    zoom = map.getZoom(),
		    precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));

		return "#" + [this.region,
			//(L.version >= '1.0.0') ? zoom.toFixed(precision) : zoom,
			zoom,
			center.lat.toFixed(precision),
			center.lng.toFixed(precision)
		].join("/");
	};

	L.Hash.prototype = {
		map: null,
		lastHash: null,
		region: undefined,

		parseHash: L.Hash.parseHash,
		formatHash: L.Hash.formatHash,

		init: function(map) {
			this.map = map;

			// reset the hash
			this.lastHash = null;
			this.onHashChange();

			if (!this.isListening) {
				this.startListening();
			}
		},

		removeFrom: function(map) {
			if (this.changeTimeout) {
				clearTimeout(this.changeTimeout);
			}

			if (this.isListening) {
				this.stopListening();
			}

			this.map = null;
		},

		onMapMove: function() {
			// bail if we're moving the map (updating from a hash),
			// or if the map is not yet loaded

			if (this.movingMap || !this.map._loaded) {
				return false;
			}

			this.autoSwitchRegionIfCloseEnough();

			var hash = this.formatHash(this.map);
			if (this.lastHash != hash) {
				location.replace(hash);
				this.lastHash = hash;
			}
		},

		autoSwitchRegionIfCloseEnough: function() {
			var minDistanceM = Number.MAX_VALUE;
			var minRegion = undefined;
			for(const key of Object.keys(rkGlobal.configurations)) {
				var distanceM = this.map.getCenter().distanceTo(rkGlobal.configurations[key].centerLatLng);
				if(distanceM < minDistanceM) {
					minDistanceM = distanceM;
					minRegion = key;
				}
			}
			if(this.region != minRegion && minDistanceM < rkGlobal.autoSwitchDistanceMeters) {
				updateRadlkarteRegion(minRegion);
				this.region = minRegion;
				console.log("auto-switching region to " + minRegion + ", map center is only " + Math.round(minDistanceM) + "m away");
				return;
			}
		},

		movingMap: false,
		update: function() {
			var hash = location.hash;
			if (hash === this.lastHash) {
				return;
			}
			var parsed = this.parseHash(hash);
			this.movingMap = true;
			if(this.region !== parsed.region) {
				// console.log('hash update got a new region, change from ' + this.region + ' to ' + parsed.region);
				updateRadlkarteRegion(parsed.region);
				this.region = parsed.region;
			}
			this.map.setView(parsed.center, parsed.zoom);
			this.movingMap = false;
		},

		// defer hash change updates every 100ms
		changeDefer: 100,
		changeTimeout: null,
		onHashChange: function() {
			// throttle calls to update() so that they only happen every
			// `changeDefer` ms
			if (!this.changeTimeout) {
				var that = this;
				this.changeTimeout = setTimeout(function() {
					that.update();
					that.changeTimeout = null;
				}, this.changeDefer);
			}
		},

		isListening: false,
		hashChangeInterval: null,
		startListening: function() {
			this.map.on("moveend", this.onMapMove, this);

			if (HAS_HASHCHANGE) {
				L.DomEvent.addListener(window, "hashchange", this.onHashChange);
			} else {
				clearInterval(this.hashChangeInterval);
				this.hashChangeInterval = setInterval(this.onHashChange, 50);
			}
			this.isListening = true;
		},

		stopListening: function() {
			this.map.off("moveend", this.onMapMove, this);

			if (HAS_HASHCHANGE) {
				L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
			} else {
				clearInterval(this.hashChangeInterval);
			}
			this.isListening = false;
		}
	};

	L.hash = function(map) {
		return new L.Hash(map);
	};

	L.Map.prototype.addHash = function() {
		this._hash = L.hash(this);
	};

	L.Map.prototype.removeHash = function() {
		this._hash.removeFrom();
	};
})(window);
<|endoftext|>