<commit_before>'use strict';

var yeoman = require('yeoman-generator'),
	yosay  = require('yosay'),
	chalk  = require('chalk');

var generator = yeoman.generators.Base.extend({

	init : function () {
		this.log(yosay('Welcome to Grep WebApp tool powered by yeoman && gulp'));
		this.log(chalk.yellow('Author : gokulkrishh (http://github.com/gokulkrishh) \n'));

		//adding flag --ng for angular
		this.option('ng', {
			desc     : 'Angular Web application',
			type     : String,
			required : true
		});

		//In end install dependencies
		this.on('end', function () {
			if(!this.options['skip-install']) {
				this.installDependencies();
			}
		});
	},

	askFor : function () {
		var done = this.async();

		this.prompt({
			type 	: 'input',
			name 	: 'appname',
			message : 'Your application name ? ',
			default : this.appname
		}, function (ans) {

			this.appname = ans.appname;
			done();
		}.bind(this));
	},
	askLib : function () {
		var done = this.async();

		var prompts = [{
			type 	: 'checkbox',
			name 	: 'libraries',
			message : 'What else you want to install ? ',
			choices : [
				{
					name 	: 'jquery',
					value   : 'addJquery',
					checked : true
				},
				{
					name 	: 'bootstrap',
					value   : 'addBootstrap',
					checked : false
				}]
			},
			{
				type 	: 'confirm',
				name 	: 'isNg',
				message : 'Is your app using angularJS ? ',
				default : false,
			},
			{
				when : function (ans) {
					return ans && ans.isNg == true;
				},
				type    : 'checkbox',
				name    : 'ngLibrary',
				message : 'Which libraries you want to install ? ',
				choices : [
				{
					name 	: 'angular-route',
					value   : 'addAngularRoute',
					checked : true
				},
				{
					name 	: 'angular-resources',
					value   : 'addAngularResources',
					checked : false
				},
				{
					name 	: 'angular-cookies',
					value   : 'addAngularCookies',
					checked : false
				},
				{
					name 	: 'angular-sanitize',
					value   : 'addAngularSanitize',
					checked : false
				},
				{
					name 	: 'angular-animate',
					value   : 'addAngularAnimate',
					checked : false
				},
				{
					name 	: 'angular-ui',
					value   : 'addAngularUI',
					checked : false
				}]
			}];

		this.prompt(prompts, function (ans) {
			function include (hasLib) {
				return ans && ans.libraries.indexOf(hasLib) !== -1;
			}

			function includeNg (hasLib) {
				if(ans.isNg == false) return false;
				return ans && ans.ngLibrary.indexOf(hasLib) !== -1;
			}

			this.jquery    			= include('addJquery');
			this.bootstrap 			= include('addBootstrap');

			if (ans.isNg) {
				this.angular   			= true;
				this.angularRoute 		= includeNg('addAngularRoute');
				this.angularResources 	= includeNg('addAngularResources');
				this.angularCookies 	= includeNg('addAngularCookies');
				this.angularAnimate 	= includeNg('addAngularAnimate');
				this.angularSanitize	= includeNg('addAngularSanitize');
				this.angularUI 			= includeNg('addAngularUI');
			}

			done();
		}.bind(this));
	},
	bower : function () {
		var bower = {
			name 		 : this.appname,
			description	 : '',
			dependencies : {}
		};

		var ngVer = '1.2.6';

		if (this.jquery) {
			bower.dependencies['jquery'] = '*';
		}

		if (this.bootstrap) {
			bower.dependencies['bootstrap'] = '*';
		}

		if (this.angular) {
			bower.dependencies['angular'] = ngVer;

			//if app is angular
			this.mkdir('app/templates');
			this.mkdir('app/js/controllers');
			this.mkdir('app/js/services');
			this.mkdir('app/js/directives');
			this.mkdir('app/js/factory');
			this.mkdir('app/js/filters');
			this.copy('_app.js', 'app/js/app.js');

			if (this.angularRoute) {
				bower.dependencies['angular-route'] = ngVer;
			}

			if (this.angularResources) {
				bower.dependencies['angular-resource'] = ngVer;
			}

			if (this.angularCookies) {
				bower.dependencies['angular-cookies'] = ngVer;
			}

			if (this.angularSanitize) {
				bower.dependencies['angular-sanitize'] = ngVer;
			}

			if (this.angularAnimate) {
				bower.dependencies['angular-animate'] = ngVer;
			}

			if (this.angularUI) {
				bower.dependencies['angular-ui'] = '*';
			}

		}

		this.write('bower.json', JSON.stringify(bower, null, 2));
	},
	appFiles : function () {
		//creating folder structure
		this.mkdir('app');
		this.mkdir('app/css');
		this.mkdir('app/js');
		this.mkdir('app/js/lib');
		this.mkdir('app/fonts');
		this.mkdir('app/images');
		this.mkdir('bower_components');

		//copy files
	    this.copy('_index.html', 'app/index.html');
	    this.copy('_main.js', 'app/js/main.js');
	    this.copy('_styles.css', 'app/css/styles.css');
	    this.copy('_app.scss', 'app/css/app.scss');
	},
	configFiles : function () {
		//copy config files
	    this.copy('_editorconfig', '.editorconfig');
	    this.copy('_jshintrc', '.jshintrc');
	    this.copy('_gitignore', '.gitignore');
	    this.copy('_bowerrc', '.bowerrc');

	    //copy gulp & pkg.json file
	    this.copy('_package.json', 'package.json');
	    this.copy('_gulpfile.js', 'gulpfile.js');
	}
});

module.exports = generator;
<commit_msg>added angular-ui-router<commit_after>'use strict';

var yeoman = require('yeoman-generator'),
	yosay  = require('yosay'),
	chalk  = require('chalk');

var generator = yeoman.generators.Base.extend({

	init : function () {
		this.log(yosay('Welcome to Grep WebApp tool powered by yeoman && gulp'));
		this.log(chalk.yellow('Author : gokulkrishh (http://github.com/gokulkrishh) \n'));

		//adding flag --ng for angular
		this.option('ng', {
			desc     : 'Angular Web application',
			type     : String,
			required : true
		});

		//In end install dependencies
		this.on('end', function () {
			if(!this.options['skip-install']) {
				this.installDependencies();
			}
		});
	},

	askFor : function () {
		var done = this.async();

		this.prompt({
			type 	: 'input',
			name 	: 'appname',
			message : 'Your application name ? ',
			default : this.appname
		}, function (ans) {

			this.appname = ans.appname;
			done();
		}.bind(this));
	},
	askLib : function () {
		var done = this.async();

		var prompts = [{
			type 	: 'checkbox',
			name 	: 'libraries',
			message : 'What else you want to install ? ',
			choices : [
				{
					name 	: 'jquery',
					value   : 'addJquery',
					checked : true
				},
				{
					name 	: 'bootstrap',
					value   : 'addBootstrap',
					checked : false
				}]
			},
			{
				type 	: 'confirm',
				name 	: 'isNg',
				message : 'Is your app using angularJS ? ',
				default : false,
			},
			{
				when : function (ans) {
					return ans && ans.isNg == true;
				},
				type    : 'checkbox',
				name    : 'ngLibrary',
				message : 'Which libraries you want to install ? ',
				choices : [
				{
					name 	: 'angular-route',
					value   : 'addAngularRoute',
					checked : true
				},
				{
					name 	: 'angular-resources',
					value   : 'addAngularResources',
					checked : false
				},
				{
					name 	: 'angular-cookies',
					value   : 'addAngularCookies',
					checked : false
				},
				{
					name 	: 'angular-sanitize',
					value   : 'addAngularSanitize',
					checked : false
				},
				{
					name 	: 'angular-animate',
					value   : 'addAngularAnimate',
					checked : false
				},
				{
					name 	: 'angular-ui-router',
					value   : 'addAngularUI',
					checked : false
				}]
			}];

		this.prompt(prompts, function (ans) {
			function include (hasLib) {
				return ans && ans.libraries.indexOf(hasLib) !== -1;
			}

			function includeNg (hasLib) {
				if(ans.isNg == false) return false;
				return ans && ans.ngLibrary.indexOf(hasLib) !== -1;
			}

			this.jquery    			= include('addJquery');
			this.bootstrap 			= include('addBootstrap');

			if (ans.isNg) {
				this.angular   			= true;
				this.angularRoute 		= includeNg('addAngularRoute');
				this.angularResources 	= includeNg('addAngularResources');
				this.angularCookies 	= includeNg('addAngularCookies');
				this.angularAnimate 	= includeNg('addAngularAnimate');
				this.angularSanitize	= includeNg('addAngularSanitize');
				this.angularUI 			= includeNg('addAngularUI');
			}

			done();
		}.bind(this));
	},
	bower : function () {
		var bower = {
			name 		 : this.appname,
			description	 : '',
			dependencies : {}
		};

		var ngVer = '1.2.6';

		if (this.jquery) {
			bower.dependencies['jquery'] = '*';
		}

		if (this.bootstrap) {
			bower.dependencies['bootstrap'] = '*';
		}

		if (this.angular) {
			bower.dependencies['angular'] = ngVer;

			//if app is angular
			this.mkdir('app/templates');
			this.mkdir('app/js/controllers');
			this.mkdir('app/js/services');
			this.mkdir('app/js/directives');
			this.mkdir('app/js/factory');
			this.mkdir('app/js/filters');
			this.copy('_app.js', 'app/js/app.js');

			if (this.angularRoute) {
				bower.dependencies['angular-route'] = ngVer;
			}

			if (this.angularResources) {
				bower.dependencies['angular-resource'] = ngVer;
			}

			if (this.angularCookies) {
				bower.dependencies['angular-cookies'] = ngVer;
			}

			if (this.angularSanitize) {
				bower.dependencies['angular-sanitize'] = ngVer;
			}

			if (this.angularAnimate) {
				bower.dependencies['angular-animate'] = ngVer;
			}

			if (this.angularUI) {
				bower.dependencies['angular-ui-router'] = '*';
			}

		}

		this.write('bower.json', JSON.stringify(bower, null, 2));
	},
	appFiles : function () {
		//creating folder structure
		this.mkdir('app');
		this.mkdir('app/css');
		this.mkdir('app/js');
		this.mkdir('app/js/lib');
		this.mkdir('app/fonts');
		this.mkdir('app/images');
		this.mkdir('bower_components');

		//copy files
	    this.copy('_index.html', 'app/index.html');
	    this.copy('_main.js', 'app/js/main.js');
	    this.copy('_styles.css', 'app/css/styles.css');
	    this.copy('_app.scss', 'app/css/app.scss');
	},
	configFiles : function () {
		//copy config files
	    this.copy('_editorconfig', '.editorconfig');
	    this.copy('_jshintrc', '.jshintrc');
	    this.copy('_gitignore', '.gitignore');
	    this.copy('_bowerrc', '.bowerrc');

	    //copy gulp & pkg.json file
	    this.copy('_package.json', 'package.json');
	    this.copy('_gulpfile.js', 'gulpfile.js');
	}
});

module.exports = generator;
<|endoftext|>


<commit_before>
(function(document, window, $){
  var apiUrl = 'http://' +  window.location.hostname + ':' + window.location.port;

  var garageDoorStatus = function(){
    return $.get(apiUrl + '/status');
  };

  var toggleGarageDoor = function(){
    return $.post(apiUrl + '/toggle');
  }

  $('#toggleBtn').on('click', function(){
    toggleGarageDoor();
  });

  setInterval(function(){
    garageDoorStatus().done(function(response){
      $('#status').text(response.text);
    });
  }, 1000)

})(document, window, $)
<commit_msg>Disable button on click :: master<commit_after>
(function(document, window, $){
  var apiUrl = 'http://' +  window.location.hostname + ':' + window.location.port;

  var garageDoorStatus = function(){
    return $.get(apiUrl + '/status');
  };

  var toggleGarageDoor = function(){
    return $.post(apiUrl + '/toggle');
  }

  $('#toggleBtn').on('click', function(){
    $('#toggleBtn').prop("disabled",true);
    toggleGarageDoor();
    setTimeout(function(){
      $('#toggleBtn').prop("disabled",false);
    }, 1000 * 10); //10 seconds
  });

  setInterval(function(){
    garageDoorStatus().done(function(response){
      $('#status').text(response.text);
    });
  }, 1000)

})(document, window, $)
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var mv = require('mv');
var async = require('async');
var mkdirp = require('mkdirp');
var absorb = require('absorb');
var path = require('path');
var util = require('util');
var yeoman = require('yeoman-generator');
var pathInstall = '';

var Generator = module.exports = function Generator(args, options) {
  yeoman.generators.Base.apply(this, arguments);
};

util.inherits(Generator, yeoman.generators.Base);

Generator.prototype.askFor = function askFor(argument) {
    var cb = this.async();
    var options = ['yes', 'no'];
    var prompts = [{
        type: 'list',
        name: 'install',
        message: 'Would you like to install a frontsize theme?',
        choices: options
    },{
        when: function (response) {
            return response.install == 'yes';
        },
        type: 'input',
        name: 'path',
        message: 'Where do you want to install frontsize theme? (Ex: css/frontsize/your_theme_name)',
        defaults: 'css/frontsize'
    }];

    this.prompt(prompts, function (props) {
        this.pathInstall = props.path;
        cb();
    }.bind(this));
};

Generator.prototype.install = function downloadFiles() {
    console.info('download');
    this.bowerInstall('frontsize-sass', { save: true });
};

Generator.prototype.end = function moveFiles() {
    console.info('move');
    var here = this;
    var directory = 'bower_components';
    var pattern = /\/$/;
    if (fs.existsSync('./.bowerrc')) {
        var obj = JSON.parse(fs.readFileSync('./.bowerrc', 'utf8'));
        if(obj.directory !== undefined){
            directory = obj.directory;
        }
    }
    directory = directory.replace(pattern, '');

    //check if package.json exists in root
    if (fs.existsSync('./package.json')) {
        var dependenciesFrontsize = '';
        var dependenciesRoot = '';

        var packageJsonFrontsize = JSON.parse(fs.readFileSync(directory + '/frontsize-sass/package.json', 'utf8'));
        if(packageJsonFrontsize.dependencies !== undefined){
            dependenciesFrontsize = packageJsonFrontsize.dependencies;
        }
        var packageJsonRoot = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
        if(packageJsonRoot.dependencies !== undefined){
            dependenciesRoot = packageJsonRoot.dependencies;
        }

        if(dependenciesRoot != ''){
            packageJsonRoot.dependencies = absorb(dependenciesRoot, dependenciesFrontsize);
        }
        else{
            packageJsonRoot.dependencies = dependenciesFrontsize;
        }

        fs.writeFile('./package.json', JSON.stringify(packageJsonRoot, null, 2), function(err) {
            if(err) {
                return console.log(err);
            }
        });
    }
    else{
        fs.createReadStream(directory + '/frontsize-sass/package.json').pipe(fs.createWriteStream('./package.json'));
    }

    //quando inserisco il path devo verificare che non esista e lo creo, se esiste gia la cartella theme al suo interno dare errore
    if(fs.exists(here.pathInstall)){
        return console.log('Path already exist!');
    }
    else{
        //create directory
        mkdirp(here.pathInstall);

        //move themes directory
        mv(directory + '/frontsize-sass/themes/default/', here.pathInstall + '/', {mkdirp: true}, function(err) {
            if((err != undefined) && (err != null)){
                return console.log('Error moving theme files! ' + err);
            }
        });

        mv(directory + '/frontsize-sass/compile.scss', here.pathInstall + '/compile.scss', function(err) {
            if((err != undefined) && (err != null)){
                return console.log('Error moving file compile.scss! ' + err);
            }
        });
    }

    /*
    /target/path/themes/nome/ --> DONE
    /target/path/compile.scss
    /gulpfile.js
    /frontsize.yml
    /package.json DONE
    */
};
<commit_msg>moving gulpfile file<commit_after>'use strict';

var fs = require('fs');
var mv = require('mv');
var async = require('async');
var mkdirp = require('mkdirp');
var absorb = require('absorb');
var path = require('path');
var util = require('util');
var yeoman = require('yeoman-generator');
var pathInstall = '';

var Generator = module.exports = function Generator(args, options) {
  yeoman.generators.Base.apply(this, arguments);
};

util.inherits(Generator, yeoman.generators.Base);

Generator.prototype.askFor = function askFor(argument) {
    var cb = this.async();
    var options = ['yes', 'no'];
    var prompts = [{
        type: 'list',
        name: 'install',
        message: 'Would you like to install a frontsize theme?',
        choices: options
    },{
        when: function (response) {
            return response.install == 'yes';
        },
        type: 'input',
        name: 'path',
        message: 'Where do you want to install frontsize theme? (Ex: css/frontsize/your_theme_name)',
        defaults: 'css/frontsize'
    }];

    this.prompt(prompts, function (props) {
        this.pathInstall = props.path;
        cb();
    }.bind(this));
};

Generator.prototype.install = function downloadFiles() {
    console.info('download');
    this.bowerInstall('frontsize-sass', { save: true });
};

Generator.prototype.end = function moveFiles() {
    console.info('move');
    var here = this;
    var directory = 'bower_components';
    var pattern = /\/$/;
    if (fs.existsSync('./.bowerrc')) {
        var obj = JSON.parse(fs.readFileSync('./.bowerrc', 'utf8'));
        if(obj.directory !== undefined){
            directory = obj.directory;
        }
    }
    directory = directory.replace(pattern, '');

    //check if package.json exists in root
    if (fs.existsSync('./package.json')) {
        var dependenciesFrontsize = '';
        var dependenciesRoot = '';

        var packageJsonFrontsize = JSON.parse(fs.readFileSync(directory + '/frontsize-sass/package.json', 'utf8'));
        if(packageJsonFrontsize.dependencies !== undefined){
            dependenciesFrontsize = packageJsonFrontsize.dependencies;
        }
        var packageJsonRoot = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
        if(packageJsonRoot.dependencies !== undefined){
            dependenciesRoot = packageJsonRoot.dependencies;
        }

        if(dependenciesRoot != ''){
            packageJsonRoot.dependencies = absorb(dependenciesRoot, dependenciesFrontsize);
        }
        else{
            packageJsonRoot.dependencies = dependenciesFrontsize;
        }

        fs.writeFile('./package.json', JSON.stringify(packageJsonRoot, null, 2), function(err) {
            if(err) {
                return console.log(err);
            }
        });
    }
    else{
        fs.createReadStream(directory + '/frontsize-sass/package.json').pipe(fs.createWriteStream('./package.json'));
    }

    //quando inserisco il path devo verificare che non esista e lo creo, se esiste gia la cartella theme al suo interno dare errore
    if(fs.exists(here.pathInstall)){
        return console.log('Path already exist!');
    }
    else{
        //create directory
        mkdirp(here.pathInstall);

        if(here.pathInstall.substr(here.pathInstall.length - 1) != '/'){
            here.pathInstall = here.pathInstall + '/';
        }

        //move themes directory
        mv(directory + '/frontsize-sass/themes/default/', here.pathInstall, {mkdirp: true}, function(err) {
            if((err != undefined) && (err != null)){
                return console.log('Error moving theme files! ' + err);
            }
            else{
                mv(directory + '/frontsize-sass/compile.scss', here.pathInstall + 'compile.scss', function(err) {
                    if((err != undefined) && (err != null)){
                        return console.log('Error moving file compile.scss! ' + err);
                    }
                    else{
                        mv(directory + '/frontsize-sass/gulpfile.js', 'gulpfile.js', function(err) {
                            if((err != undefined) && (err != null)){
                                return console.log('Error moving file gulpfile.js! ' + err);
                            }
                        });
                    }
                });
            }
        });
    }

    /*
    /target/path/themes/nome/ --> DONE
    /target/path/compile.scss
    /gulpfile.js
    /frontsize.yml
    /package.json DONE
    */
};
<|endoftext|>


<commit_before>(function($) {
    'use strict';

    var TKSWeb = window.TKSWeb = {
        day_name          : [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ],
        month_name        : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
        hour_label_width  : 50,
        hour_label_height : 50,
        day_label_width   : 200,
        day_label_height  : 28
    };
    var week_days, hours, column_for_date;

    function init_hours() {
        hours = [];
        for(var i = 0; i < 24; i++) {
            hours.push({ hour: pad2(i) + ':00' });
        }
    }

    function init_week_days(days) {
        column_for_date = {};
        week_days       = [];
        for(var i = 0; i < 7; i++) {
            column_for_date[ days[i] ] = i;
            var part = days[i].split('-');
            week_days.push({
                date      : days[i],
                day       : part[2],
                month     : part[1],
                year      : part[0],
                day_name  : TKSWeb.day_name[ i ],
                month_name: TKSWeb.month_name[ parseInt(part[1], 10) - 1 ],
            });
        }
    };

    function pad2(num) {
        return num < 10 ? '0' + num : '' + num;
    }

    var Activity = Backbone.Model.extend({
        defaults: {
            date          : '',
            start_time    : 0,
            duration      : 60,
            wr_number     : '',
            description   : ''
        },
        initialize: function() {
            this.set('column', column_for_date[ this.get('date') ]);
        }
    });

    var Activities = Backbone.Collection.extend({
        model: Activity,
        url: '/activity'
    });

    var ActivityView = Backbone.View.extend({
        tagName: 'div',
        className: 'activity',

        initialize: function() {
            this.week_view = this.model.collection.view;
            this.listenTo(this.model, "change:wr_number change:description", this.render);
            this.position_element();
            this.size_element();
        },

        render: function() {
            var context = this.model.toJSON();
            this.$el.html( this.week_view.activity_template(context) );
            return this;
        },
        position_element: function() {
            var activity = this.model;
            this.$el.css({
                left: activity.get('column') * 200,
                top:  (activity.get('start_time') * 50) / 60
            });
        },
        size_element: function() {
            var activity = this.model;
            this.$el.height(activity.get('duration') * 50 / 60);
        }
    });

    var WeekView = Backbone.View.extend({
        initialize: function(options) {
            var view = this;
            this.compile_templates();
            this.render();
            this.collection.on('add', this.add_activity, this);
            this.$('.activities').on('mousewheel', $.proxy(this.mousewheel, this));
            $(window).resize( $.proxy(view.resize, view) );
        },
        compile_templates: function() {
            this.template = Handlebars.compile( $('#week-view-template').html() );
            this.activity_template = Handlebars.compile( $('#activity-template').html() );
        },
        render: function() {
            var context = {
                week_days: week_days,
                hours: hours
            };
            this.$el.html( this.template(context) );
            this.size_activities();
            this.enable_workspace_drag();
            this.resize();
        },
        size_activities: function() {
            this.activities_width  = TKSWeb.day_label_width * 7;
            this.activities_height = TKSWeb.hour_label_height * 24;
            this.$('.activities')
                .width(this.activities_width)
                .height(this.activities_height);
            this.$('.day-labels')
                .width(this.activities_width)
                .height(TKSWeb.day_label_height);
            this.$('.hour-labels')
                .width(TKSWeb.hour_label_width)
                .height(this.activities_height);
        },
        enable_workspace_drag: function() {
            var view = this;
            this.$('.activities').draggable({
                drag: function(event, ui) { view.drag( ui.position ); }
            });
        },
        resize: function() {
            this.app_width  = Math.min(this.activities_width + TKSWeb.hour_label_width, window.innerWidth);
            this.app_height = Math.min(this.activities_height + TKSWeb.day_label_height, window.innerHeight);
            this.$el.width( this.app_width ).height( this.app_height );
            this.set_drag_constraints();
        },
        set_drag_constraints: function() {
            this.min_y = this.app_height - this.activities_height;
            this.max_y = TKSWeb.day_label_height + 1;
            this.$('.activities').draggable("option", {
                containment: [
                    this.app_width - this.activities_width,
                    this.min_y,
                    TKSWeb.hour_label_width + 1,
                    this.max_y
                ]
            });
        },
        drag: function(pos) {
            this.$('.day-labels ul').css('left', pos.left - TKSWeb.hour_label_width);
            this.$('.hour-labels ul').css('top', pos.top - TKSWeb.day_label_height);
        },
        mousewheel: function(e, delta) {
            var $activities = this.$('.activities');
            var y = parseInt($activities.css('top'), 10) + delta * 12;
            y = Math.min( Math.max(y, this.min_y), this.max_y);
            $activities.css('top', y);
            this.$('.hour-labels ul').css('top', y - TKSWeb.day_label_height);
        },
        add_activity: function(activity) {
            this.$('.activities').append(
                new ActivityView({
                    model: activity
                }).render().el
            );
        }
    });

    TKSWeb.show_week = function (el, days, activities_data) {
        init_week_days(days);
        init_hours();
        var activities = new Activities();
        activities.view = new WeekView({
            el: el,
            monday: days[0],
            collection: activities
        });
        activities.add(activities_data);
    };

})(jQuery);
<commit_msg>add a comparator function to order activities by date/time<commit_after>(function($) {
    'use strict';

    var TKSWeb = window.TKSWeb = {
        day_name          : [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ],
        month_name        : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
        hour_label_width  : 50,
        hour_label_height : 50,
        day_label_width   : 200,
        day_label_height  : 28
    };
    var week_days, hours, column_for_date;

    function init_hours() {
        hours = [];
        for(var i = 0; i < 24; i++) {
            hours.push({ hour: pad2(i) + ':00' });
        }
    }

    function init_week_days(days) {
        column_for_date = {};
        week_days       = [];
        for(var i = 0; i < 7; i++) {
            column_for_date[ days[i] ] = i;
            var part = days[i].split('-');
            week_days.push({
                date      : days[i],
                day       : part[2],
                month     : part[1],
                year      : part[0],
                day_name  : TKSWeb.day_name[ i ],
                month_name: TKSWeb.month_name[ parseInt(part[1], 10) - 1 ],
            });
        }
    };

    function pad2(num) {
        return num < 10 ? '0' + num : '' + num;
    }

    var Activity = Backbone.Model.extend({
        defaults: {
            date          : '',
            start_time    : 0,
            duration      : 60,
            wr_number     : '',
            description   : ''
        },
        initialize: function() {
            this.set('column', column_for_date[ this.get('date') ]);
        }
    });

    var Activities = Backbone.Collection.extend({
        model: Activity,
        url: '/activity',
        comparator: function(activity) {
            return activity.get("date") + ' ' +
                   ('0000' + activity.get("start_time")).substr(-4);
        }
    });

    var ActivityView = Backbone.View.extend({
        tagName: 'div',
        className: 'activity',

        initialize: function() {
            this.week_view = this.model.collection.view;
            this.listenTo(this.model, "change:wr_number change:description", this.render);
            this.position_element();
            this.size_element();
        },

        render: function() {
            var context = this.model.toJSON();
            this.$el.html( this.week_view.activity_template(context) );
            return this;
        },
        position_element: function() {
            var activity = this.model;
            this.$el.css({
                left: activity.get('column') * 200,
                top:  (activity.get('start_time') * 50) / 60
            });
        },
        size_element: function() {
            var activity = this.model;
            this.$el.height(activity.get('duration') * 50 / 60);
        }
    });

    var WeekView = Backbone.View.extend({
        initialize: function(options) {
            var view = this;
            this.compile_templates();
            this.render();
            this.collection.on('add', this.add_activity, this);
            this.$('.activities').on('mousewheel', $.proxy(this.mousewheel, this));
            $(window).resize( $.proxy(view.resize, view) );
        },
        compile_templates: function() {
            this.template = Handlebars.compile( $('#week-view-template').html() );
            this.activity_template = Handlebars.compile( $('#activity-template').html() );
        },
        render: function() {
            var context = {
                week_days: week_days,
                hours: hours
            };
            this.$el.html( this.template(context) );
            this.size_activities();
            this.enable_workspace_drag();
            this.resize();
        },
        size_activities: function() {
            this.activities_width  = TKSWeb.day_label_width * 7;
            this.activities_height = TKSWeb.hour_label_height * 24;
            this.$('.activities')
                .width(this.activities_width)
                .height(this.activities_height);
            this.$('.day-labels')
                .width(this.activities_width)
                .height(TKSWeb.day_label_height);
            this.$('.hour-labels')
                .width(TKSWeb.hour_label_width)
                .height(this.activities_height);
        },
        enable_workspace_drag: function() {
            var view = this;
            this.$('.activities').draggable({
                drag: function(event, ui) { view.drag( ui.position ); }
            });
        },
        resize: function() {
            this.app_width  = Math.min(this.activities_width + TKSWeb.hour_label_width, window.innerWidth);
            this.app_height = Math.min(this.activities_height + TKSWeb.day_label_height, window.innerHeight);
            this.$el.width( this.app_width ).height( this.app_height );
            this.set_drag_constraints();
        },
        set_drag_constraints: function() {
            this.min_y = this.app_height - this.activities_height;
            this.max_y = TKSWeb.day_label_height + 1;
            this.$('.activities').draggable("option", {
                containment: [
                    this.app_width - this.activities_width,
                    this.min_y,
                    TKSWeb.hour_label_width + 1,
                    this.max_y
                ]
            });
        },
        drag: function(pos) {
            this.$('.day-labels ul').css('left', pos.left - TKSWeb.hour_label_width);
            this.$('.hour-labels ul').css('top', pos.top - TKSWeb.day_label_height);
        },
        mousewheel: function(e, delta) {
            var $activities = this.$('.activities');
            var y = parseInt($activities.css('top'), 10) + delta * 12;
            y = Math.min( Math.max(y, this.min_y), this.max_y);
            $activities.css('top', y);
            this.$('.hour-labels ul').css('top', y - TKSWeb.day_label_height);
        },
        add_activity: function(activity) {
            this.$('.activities').append(
                new ActivityView({
                    model: activity
                }).render().el
            );
        }
    });

    TKSWeb.show_week = function (el, days, activities_data) {
        init_week_days(days);
        init_hours();
        var activities = new Activities();
        activities.view = new WeekView({
            el: el,
            monday: days[0],
            collection: activities
        });
        activities.add(activities_data);
    };

})(jQuery);
<|endoftext|>


<commit_before>import {getApi} from '../common/oauth';
const remote = require('electron').remote;
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
const clipboard = require('electron').clipboard;
const Vue = require('vue');
var setting = JSON.parse(localStorage["ulttwiclient"]);
console.log(setting.tokens);

window.addEventListener('load',()=>{
  Vue.filter('expand_url', function (text, entities){
    entities.urls.forEach((url)=>{
      text = text.replace(url.url, url.display_url);
    });
    if (entities.media) {
      entities.media.forEach((m)=>{
        text = text.replace(m.url, m.display_url);
      });
    }
    return text;
  });
  // context menu on status
  var contextMenuTweet = new Menu();
  contextMenuStatus.append(new MenuItem({label: "ツイートに返信する", click: ()=>{vm.sendReply(vm.selectedTweet);}}));
  contextMenuStatus.append(new MenuItem({label: "ツイートをふぁぼる", click: ()=>{vm.favoriteTweet(vm.selectedTweet);}}));
  contextMenuStatus.append(new MenuItem({type: 'separator'}));
  contextMenuStatus.append(new MenuItem({label: "ツイートのJSONを取得", click: ()=>{clipboard.writeText(JSON.stringify(vm.selectedTweet));}}));
  var vm = new Vue({
    el: "#container",
    data: {
      newTweet: {
        text: "",
        in_reply_to_status_id: ""
      },
      selectedTweet: {},
      me: {},
      streaming: false,
      showingImage: false,
      image: {},
      tweets: [],
      notifications: []
    },
    computed: {
      calculateRemainChar: function() {
        return 140 - this.newTweet.text.length;
      }
    },
    methods: {
      sendTweet: function (params) {
        api.post('statuses/update', {
          status: params.text,
          in_reply_to_status_id: params.in_reply_to_status_id
        }, (error, tweet, response)=>{
          if (error) {
            this.createNotification("ツイートの投稿に失敗しました", this.newTweet.text, null, 'fail');
            return console.log('error', error.map((e)=>e.message).join("\n"),  error);
          }
          console.log(tweet, response);
          this.createNotification("ツイートが投稿されました", this.newTweet.text, null, 'tweet');
          this.newTweet.text = '';
          this.newTweet.in_reply_to_status_id = '';
        });
      },
      clearReply: function () {
        this.newTweet.text = this.newTweet.text.replace(/@[a-zA-Z0-9_]+/g, '');
        this.newTweet.in_reply_to_status_id = '';
      },
      startStreaming: function () {
        console.info("start streaming");
        this.streaming = true;
        api.stream('user', {}, (stream)=>{
          stream.on('data', (data)=>{
            console.log(data);
            if (data.friends) {
              return;
            } else if (data.delete) {
              console.log(data.delete);
              this.deleteTweet(data.delete.status.id_str);
            } else if (data.scrub_geo) {
              // location deletion
            } else if (data.limit) {
              // limit notices
            } else if (data.status_withheld) {
              // withheld content notices (status)
            } else if (data.user_withheld) {
              // withheld content notices (user)
            } else if (data.disconnect) {
              // disconnect messages
            } else if (data.warning) {
              // stall warnings
            } else if (data.event) {
              // catch some event
            } else {
              // status
              this.tweets.push(data);
              if (this.isMentionsForYou(data)) {
                this.createNotification("あなた宛のメンションがあります", data.text, data.user.profile_image_url_https, 'tweet');
              }
            }
          });
          stream.on('favorite', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification("あなたのツイートがいいねされました", data.target_object.text, data.target.profile_image_url_https, 'favorite');
            }
          });
          stream.on('unfavorite', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification("あなたのツイートがいいね取り消しされました", data.target_object.text, data.target.profile_image_url_https, 'unfavorite');
            }
          });
          stream.on('follow', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification(data.source.name + " さんにフォローされました", data.source.description, data.source.profile_image_url_https, 'follow');
            }
          });
          stream.on('list_member_added', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification(data.source.name + " さんにリスト "+data.target_object.name+" に追加されました", data.target_object.description, data.source.profile_image_url_https, 'list_member_added');
            }
          });
        });
      },
      favoriteTweet: function (tweet) {
        console.log(tweet.id_str);
        var favorites_url = tweet.favorited ? 'favorites/destroy' : 'favorites/create';
        var favorites_id = tweet.retweeted_status ? tweet.retweeted_status.id_str : tweet.id_str
        api.post(favorites_url, {id: favorites_id}, (error, _tweet, response)=>{
          if (error) {
            this.createNotification("ツイートをいいねできませんでした", tweet.text, null, 'fail');
            return console.log('error', error.map((e)=>e.message).join("\n"),  error);
          }
          console.log(_tweet, response);
          if (tweet.favorited)
            this.createNotification("ツイートをいいね取り消ししました", tweet.text, null, 'unfavorite');
          else
            this.createNotification("ツイートをいいねしました", tweet.text, null, 'favorite');
          tweet.favorited = _tweet.favorited;
          tweet.favotite_count = _tweet.favorite_count;
        });
      },
      showImage: function(url, size) {
        this.image = {url: url, width: size.w, height: size.h};
        this.showingImage = true;
      },
      closeImage: function() {
        this.image = {};
        this.showingImage = false;
      },
      sendReply: function(tweet) {
        console.log(tweet.id_str);
        this.newTweet.text = "@" + tweet.user.screen_name + " ";
        this.newTweet.in_reply_to_status_id = tweet.id_str;
        this.$els.submit_box.focus();
      },
      hasMedias: function(tweet) {
        return 'extended_entities' in tweet && 'media' in tweet.extended_entities;
      },
      isMentionsForYou: function(tweet) {
        return tweet.text.match('@' + this.me.screen_name);
      },
      deleteTweet: function(id_str) {
        this.tweets.forEach((t,i) => {
          if (t.id_str === id_str)
            this.tweets.splice(i, 1);
        })
      },
      createNotification: function(title, body, icon, kind) {
        let notification = {title, body, kind};
        this.notifications.push(notification);
        const removeMSecond = 6000;
        window.setTimeout(()=>{
          removeNotification(notification);
        }, removeMSecond);
        if (!remote.getCurrentWindow().isFocused()) {
          new Notification(title, {icon: icon, body: body});
        }
      },
      removeNotification: function(notification) {
        this.notifications.forEach((n,i) => {
          if (n === notification)
            this.notifications.splice(i, 1);
        })
      },
      contextMenuOnTweet: function(tweet) {
        this.selectedTweet = tweet;
        contextMenuTweet.popup(remote.getCurrentWindow());
      }
    }
  });
  if(setting.tokens){
    var api = getApi(setting.tokens);
    api.get('account/verify_credentials', {}, (error, data, response)=>{
      if (error) {
        return console.log('error', error.map((e)=>e.message).join("\n"),  error);
      }
      vm.me = data;
    });
    api.get('statuses/home_timeline', {count: 200}, function(error, tweets, response){
      if (error) {
        console.log('error', error.map((e)=>e.message).join("\n"),  error);
      }
      console.log('tweets',tweets.map((t)=>t.text).join("\n"), tweets);
      tweets.forEach((tweet)=>{
        vm.tweets.push(tweet);
      });
    });
    vm.startStreaming();
  }else{
    console.warn("did not oauth");
  }
});
<commit_msg>Menu.buildFromTemplate<commit_after>import {getApi} from '../common/oauth';
const remote = require('electron').remote;
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
const clipboard = require('electron').clipboard;
const Vue = require('vue');
var setting = JSON.parse(localStorage["ulttwiclient"]);
console.log(setting.tokens);

window.addEventListener('load',()=>{
  Vue.filter('expand_url', function (text, entities){
    entities.urls.forEach((url)=>{
      text = text.replace(url.url, url.display_url);
    });
    if (entities.media) {
      entities.media.forEach((m)=>{
        text = text.replace(m.url, m.display_url);
      });
    }
    return text;
  });
  // context menu on status
  var contextMenuTweet = Menu.buildFromTemplate([
    {label: "ツイートに返信する", click: ()=>{vm.sendReply(vm.selectedTweet);}},
    {label: "ツイートをふぁぼる", click: ()=>{vm.favoriteTweet(vm.selectedTweet);}},
    {type: 'separator'},
    {label: "ツイートのJSONを取得", click: ()=>{clipboard.writeText(JSON.stringify(vm.selectedTweet));}}
  ]);
  var vm = new Vue({
    el: "#container",
    data: {
      newTweet: {
        text: "",
        in_reply_to_status_id: ""
      },
      selectedTweet: {},
      me: {},
      streaming: false,
      showingImage: false,
      image: {},
      tweets: [],
      notifications: []
    },
    computed: {
      calculateRemainChar: function() {
        return 140 - this.newTweet.text.length;
      }
    },
    methods: {
      sendTweet: function (params) {
        api.post('statuses/update', {
          status: params.text,
          in_reply_to_status_id: params.in_reply_to_status_id
        }, (error, tweet, response)=>{
          if (error) {
            this.createNotification("ツイートの投稿に失敗しました", this.newTweet.text, null, 'fail');
            return console.log('error', error.map((e)=>e.message).join("\n"),  error);
          }
          console.log(tweet, response);
          this.createNotification("ツイートが投稿されました", this.newTweet.text, null, 'tweet');
          this.newTweet.text = '';
          this.newTweet.in_reply_to_status_id = '';
        });
      },
      clearReply: function () {
        this.newTweet.text = this.newTweet.text.replace(/@[a-zA-Z0-9_]+/g, '');
        this.newTweet.in_reply_to_status_id = '';
      },
      startStreaming: function () {
        console.info("start streaming");
        this.streaming = true;
        api.stream('user', {}, (stream)=>{
          stream.on('data', (data)=>{
            console.log(data);
            if (data.friends) {
              return;
            } else if (data.delete) {
              console.log(data.delete);
              this.deleteTweet(data.delete.status.id_str);
            } else if (data.scrub_geo) {
              // location deletion
            } else if (data.limit) {
              // limit notices
            } else if (data.status_withheld) {
              // withheld content notices (status)
            } else if (data.user_withheld) {
              // withheld content notices (user)
            } else if (data.disconnect) {
              // disconnect messages
            } else if (data.warning) {
              // stall warnings
            } else if (data.event) {
              // catch some event
            } else {
              // status
              this.tweets.push(data);
              if (this.isMentionsForYou(data)) {
                this.createNotification("あなた宛のメンションがあります", data.text, data.user.profile_image_url_https, 'tweet');
              }
            }
          });
          stream.on('favorite', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification("あなたのツイートがいいねされました", data.target_object.text, data.target.profile_image_url_https, 'favorite');
            }
          });
          stream.on('unfavorite', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification("あなたのツイートがいいね取り消しされました", data.target_object.text, data.target.profile_image_url_https, 'unfavorite');
            }
          });
          stream.on('follow', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification(data.source.name + " さんにフォローされました", data.source.description, data.source.profile_image_url_https, 'follow');
            }
          });
          stream.on('list_member_added', (data)=>{
            if (data.target.screen_name === this.me.screen_name) {
              this.createNotification(data.source.name + " さんにリスト "+data.target_object.name+" に追加されました", data.target_object.description, data.source.profile_image_url_https, 'list_member_added');
            }
          });
        });
      },
      favoriteTweet: function (tweet) {
        console.log(tweet.id_str);
        var favorites_url = tweet.favorited ? 'favorites/destroy' : 'favorites/create';
        var favorites_id = tweet.retweeted_status ? tweet.retweeted_status.id_str : tweet.id_str
        api.post(favorites_url, {id: favorites_id}, (error, _tweet, response)=>{
          if (error) {
            this.createNotification("ツイートをいいねできませんでした", tweet.text, null, 'fail');
            return console.log('error', error.map((e)=>e.message).join("\n"),  error);
          }
          console.log(_tweet, response);
          if (tweet.favorited)
            this.createNotification("ツイートをいいね取り消ししました", tweet.text, null, 'unfavorite');
          else
            this.createNotification("ツイートをいいねしました", tweet.text, null, 'favorite');
          tweet.favorited = _tweet.favorited;
          tweet.favotite_count = _tweet.favorite_count;
        });
      },
      showImage: function(url, size) {
        this.image = {url: url, width: size.w, height: size.h};
        this.showingImage = true;
      },
      closeImage: function() {
        this.image = {};
        this.showingImage = false;
      },
      sendReply: function(tweet) {
        console.log(tweet.id_str);
        this.newTweet.text = "@" + tweet.user.screen_name + " ";
        this.newTweet.in_reply_to_status_id = tweet.id_str;
        this.$els.submit_box.focus();
      },
      hasMedias: function(tweet) {
        return 'extended_entities' in tweet && 'media' in tweet.extended_entities;
      },
      isMentionsForYou: function(tweet) {
        return tweet.text.match('@' + this.me.screen_name);
      },
      deleteTweet: function(id_str) {
        this.tweets.forEach((t,i) => {
          if (t.id_str === id_str)
            this.tweets.splice(i, 1);
        })
      },
      createNotification: function(title, body, icon, kind) {
        let notification = {title, body, kind};
        this.notifications.push(notification);
        const removeMSecond = 6000;
        window.setTimeout(()=>{
          removeNotification(notification);
        }, removeMSecond);
        if (!remote.getCurrentWindow().isFocused()) {
          new Notification(title, {icon: icon, body: body});
        }
      },
      removeNotification: function(notification) {
        this.notifications.forEach((n,i) => {
          if (n === notification)
            this.notifications.splice(i, 1);
        })
      },
      contextMenuOnTweet: function(tweet) {
        this.selectedTweet = tweet;
        contextMenuTweet.popup(remote.getCurrentWindow());
      }
    }
  });
  if(setting.tokens){
    var api = getApi(setting.tokens);
    api.get('account/verify_credentials', {}, (error, data, response)=>{
      if (error) {
        return console.log('error', error.map((e)=>e.message).join("\n"),  error);
      }
      vm.me = data;
    });
    api.get('statuses/home_timeline', {count: 200}, function(error, tweets, response){
      if (error) {
        console.log('error', error.map((e)=>e.message).join("\n"),  error);
      }
      console.log('tweets',tweets.map((t)=>t.text).join("\n"), tweets);
      tweets.forEach((tweet)=>{
        vm.tweets.push(tweet);
      });
    });
    vm.startStreaming();
  }else{
    console.warn("did not oauth");
  }
});
<|endoftext|>


<commit_before>var map;
var userLocation;
var userMarker;

$(function() {
    console.log("Document is ready!");
});

function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: {
            lat: -34.397,
            lng: 150.644
        },
        zoom: 8
    });

    map.addListener('click', function(event) {
        console.log(event.latLng.lat() + ", " + event.latLng.lng())
    });

    navigator.geolocation.getCurrentPosition(function(position) {
        console.log(position)

        // userLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
        // userLocation = new google.maps.LatLng(25.015384309623297, 121.53891563415527)
        userLocation = new google.maps.LatLng(25.033661079435696, 121.51153564453125)

        map.setCenter(userLocation);
        map.setZoom(14);

        addUserMarker(userLocation, map);

        // Testing
        // calcRoute(userLocation, aMapsLatLng(25.1, 121.56), map)

        // Testing
        getBlockWithinDistance(1)

    });

    // Testing
    // drawLinesOnMap([aLocation(25.02, 121.534), aLocation(25.03, 121.534)], map)
    // drawCarDataOnMap(carData, map)

    // Testing
    drawCrossRoadsMarkersOnMap(map)

    // Testing
    getDataFromServer()
}

function addUserMarker(location, map) {
    userMarker = new google.maps.Marker({
        map: map,
        position: location,
        title: "My Position"
    });
    // console.log(location, map);
}

// Helper --> {"lat":lat, "lng":lng}
function aLocation(lat, lng) {
    return {
        "lat": lat,
        "lng": lng
    }
}

// Helper (121, 25) --> google.maps.LatLng
function aMapsLatLng(lat, lng) {
    return new google.maps.LatLng(lat, lng)
}

// ==== Basic helper ====
function drawLinesOnMap(path, map, color) {
    var lines = new google.maps.Polyline({
        path: path,
        geodesic: true,
        strokeColor: color,
        strokeOpacity: 0.7,
        strokeWeight: 4
    });
    lines.setMap(map);
}

var directionsService;
var directionsRender;

function calcRoute(originLoc, destinationLoc, map) {

    directionsService = new google.maps.DirectionsService();
    directionsRender = new google.maps.DirectionsRenderer();
    directionsRender.setMap(map);

    var request = {
        origin: originLoc,
        destination: destinationLoc,
        optimizeWaypoints: true,
        travelMode: google.maps.TravelMode.WALKING
    }

    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsRender.setDirections(response);
        }
    });
}

function drawAMakerOnMap(coordsStringArray, map, title, image) {
    var latLng = aLocation(parseFloat(coordsStringArray[0]), parseFloat(coordsStringArray[1]));

    var marker = new google.maps.Marker({
        position: latLng,
        map: map,
        title: title,
        icon: image
    });

}

// ==== Draw events ====
function drawCrossRoadMarkerOnMap(coordsStringArray, map) {

    drawAMakerOnMap(coordsStringArray, map, '交叉路口', '/static/img/cir3.png')

}

function drawCrossRoadsMarkersOnMap(map) {

    for (var i = 0; i < cross_road_data.length; i++) {
        drawCrossRoadMarkerOnMap(cross_road_data[i], map)
    };

}

function drawCarDataOnMap(liveCarData, map) {

    var results = liveCarData;

    for (var i = 0; i < results.length; i++) {

        var color = "#3eb076" // green
        if (parseFloat(results[i].AvgOcc) > 7) {
            color = "#bb3d15"
        }

        drawLinesOnMap([aLocation(parseFloat(results[i].StartWgsY), parseFloat(results[i].StartWgsX)), aLocation(parseFloat(results[i].EndWgsY), parseFloat(results[i].EndWgsX))], map, color)
    };

}

//
function addCarsDataToGridLine(aLiveCarData) {
    var startLng = parseFloat(aLiveCarData.StartWgsY)
    var startLat = parseFloat(aLiveCarData.StartWgsX)
    var endLng = parseFloat(aLiveCarData.EndWgsY)
    var endLat = parseFloat(aLiveCarData.EndWgsX)
    classifyLine({
        lat: startLat,
        lng: startLng
    }, {
        lat: endLat,
        lng: endLng
    }, parseFloat(aLiveCarData.AvgOcc))
}

function drawConstructionSiteOnMap(constructionData, map) {

    for (var i = 0; i < constructionData.length; i++) {
        drawAMakerOnMap([constructionData[i].X, constructionData[i].Y], map, '施工地點', '/static/img/construction_small.png')
    };

}

function drawCrimeSiteOnMap(crimeData, map) {
    for (var i = 0; i < crimeData.length; i++) {
        drawAMakerOnMap([crimeData[i].lat, crimeData[i].lng], map, '常犯罪地點', '/static/img/danger_small.png')
    };

}

function drawParkOnMap(parkData, map) {
    for (var i = 0; i < parkData.length; i++) {
        drawAMakerOnMap([parkData[i].lat, parkData[i].lng], map, '公園', '')
    };
}

// ==== Get Live Data ====
function getDataFromServer() {
    console.log('get server data')
    $.get('http://localhost:3000/getdata', function(result) {
        // console.log(result)

        result = JSON.parse(result)

        var carsData = result.cars.data
        var crime = result.crime.data
        var park = result.park.data
        var constructions = result.constructions.data
        var uv = result.uv.data
        var airquality = result.airquality.data

        // console.log("carsData: " + carsData)

        // Draw all on map
        drawCarDataOnMap(carsData, map)
        drawConstructionSiteOnMap(constructions, map)
        drawCrimeSiteOnMap(crime, map)

        // Add to grid system
        for (var i = 0; i < constructions.length; i++) {
            addConstructionSiteToGrid(constructions[i])
        };

        for (var i = 0; i < crime.length; i++) {
            addCrimeSiteToGrid(crime[i])
        };

        for (var i = 0; i < carsData.length; i++) {
            addCarsDataToGridLine(carsData[i])
        };

        // console.log(JSON.stringify(grid))
    })
}

function gf(string) {
    return parseFloat(string)
}

// Type: Construction: 1, Crime: 2,
function addConstructionSiteToGrid(aConstruction) {
    classify(gf(aConstruction.X), gf(aConstruction.Y), 1)
}

function addCrimeSiteToGrid(aCrimeSiteData) {
    classify(gf(aCrimeSiteData.lat), gf(aCrimeSiteData.lng), 2)
}

function getBlockWithinDistance(distanceWithinAsKm) {

    directionsService = new google.maps.DirectionsService();
    directionsRender = new google.maps.DirectionsRenderer();

    var list = []

    for (var i = 0; i < cross_road_data.length; i++) {

        var itsDistance = calcCrow(userLocation.lat(), userLocation.lng(), parseFloat(cross_road_data[i][0]), parseFloat(cross_road_data[i][1]));

        if (itsDistance <= distanceWithinAsKm) {
            console.log('smaller')

            console.log()

            // drawAMakerOnMap([cross_road_data[i][0], cross_road_data[i][1]], map, 'Smaller', '')

            var request = {
                origin: aMapsLatLng(userLocation.lat(), userLocation.lng()),
                destination: aMapsLatLng(parseFloat(cross_road_data[i][0]), parseFloat(cross_road_data[i][1])),
                optimizeWaypoints: true,
                travelMode: google.maps.TravelMode.WALKING
            }

            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    var sublist = [];

                    var allGridsForThisLeg = []

                    for (var j = 0; j < response.routes[0].legs[0].steps.length; j++) {

                        var startPoint = response.routes[0].legs[0].steps[j].start_point;
                        var endPoint = response.routes[0].legs[0].steps[j].end_point;

                        sublist.push({
                            start: startPoint,
                            end: endPoint
                        });

                        var legGrid = getGridsThrough({
                                "lat": startPoint.G,
                                "lng": startPoint.K
                            }, {
                                "lat": endPoint.G,
                                "lng": endPoint.K
                            })
                            // console.log("legGrid step" + j + ": " + JSON.stringify(legGrid))
                            // console.log(startPoint + endPoint)

                        allGridsForThisLeg = _.union(allGridsForThisLeg, legGrid)

                    }

                    console.log("score: " + calculateScoreFromAllGrids(allGridsForThisLeg))
                    directionsRender.setDirections(response)

                    // console.log("All grid: " + allGridsForThisLeg)

                    list.push(sublist);
                    // console.log(JSON.stringify(list))
                } else {
                    console.log('Google Maps route failed ' + status)
                }
            });
        }
    };

}

function calculateScoreFromAllGrids(allGrids) {
    var finalScore = 100;
    //console.log('grid:',grid);
    //console.log('allGrids',allGrids);
    for (var i = 0; i < allGrids.length; i++) {
        var key = allGrids[i];
        if (!(key in grid)) {
            //console.log('key not found in grid')
        } else {
            var event = grid[key]["event"];
            var traffic = grid[key]["traffic"];

            var type1Count = 0;
            var type2Count = 0;
            for (var j = 0; j < event.length; j++) {
                if (event[j]["type"] == '1') {
                    type1Count++
                } else {
                    type2Count++
                }
            };

            finalScore = finalScore - (3 * type2Count) - (1 * type1Count) - (3 * traffic)
        }

        var score = grid[key]
    };
    return finalScore
}

//This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
function calcCrow(lat1, lon1, lat2, lon2) {
    var R = 6371; // km
    var dLat = toRad(lat2 - lat1);
    var dLon = toRad(lon2 - lon1);
    var lat1 = toRad(lat1);
    var lat2 = toRad(lat2);

    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return d;
}

// Converts numeric degrees to radians
function toRad(Value) {
    return Value * Math.PI / 180;
}
<commit_msg>finish drawing polylines<commit_after>var map;
var userLocation;
var userMarker;

$(function() {
    console.log("Document is ready!");
});

function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: {
            lat: -34.397,
            lng: 150.644
        },
        zoom: 8
    });

    map.addListener('click', function(event) {
        console.log(event.latLng.lat() + ", " + event.latLng.lng())
    });

    navigator.geolocation.getCurrentPosition(function(position) {
        console.log(position)

        // userLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
        // userLocation = new google.maps.LatLng(25.015384309623297, 121.53891563415527)
        userLocation = new google.maps.LatLng(25.033661079435696, 121.51153564453125)

        map.setCenter(userLocation);
        map.setZoom(14);

        addUserMarker(userLocation, map);

        // Testing
        // calcRoute(userLocation, aMapsLatLng(25.1, 121.56), map)

        // Testing
        getBlockWithinDistance(1)

    });

    // Testing
    // drawLinesOnMap([aLocation(25.02, 121.534), aLocation(25.03, 121.534)], map)
    // drawCarDataOnMap(carData, map)

    // Testing
    drawCrossRoadsMarkersOnMap(map)

    // Testing
    getDataFromServer()
}

function addUserMarker(location, map) {
    userMarker = new google.maps.Marker({
        map: map,
        position: location,
        title: "My Position"
    });
    // console.log(location, map);
}

// Helper --> {"lat":lat, "lng":lng}
function aLocation(lat, lng) {
    return {
        "lat": lat,
        "lng": lng
    }
}

// Helper (121, 25) --> google.maps.LatLng
function aMapsLatLng(lat, lng) {
    return new google.maps.LatLng(lat, lng)
}

// ==== Basic helper ====
function drawLinesOnMap(path, map, color) {
    var lines = new google.maps.Polyline({
        path: path,
        geodesic: true,
        strokeColor: color,
        strokeOpacity: 0.7,
        strokeWeight: 4
    });
    lines.setMap(map);
}

var directionsService;
var directionsRender;

function calcRoute(originLoc, destinationLoc, map) {

    directionsService = new google.maps.DirectionsService();
    directionsRender = new google.maps.DirectionsRenderer();
    directionsRender.setMap(map);

    var request = {
        origin: originLoc,
        destination: destinationLoc,
        optimizeWaypoints: true,
        travelMode: google.maps.TravelMode.WALKING
    }

    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsRender.setDirections(response);
        }
    });
}

function drawAMakerOnMap(coordsStringArray, map, title, image) {
    var latLng = aLocation(parseFloat(coordsStringArray[0]), parseFloat(coordsStringArray[1]));

    var marker = new google.maps.Marker({
        position: latLng,
        map: map,
        title: title,
        icon: image
    });

}

// ==== Draw events ====
function drawCrossRoadMarkerOnMap(coordsStringArray, map) {

    drawAMakerOnMap(coordsStringArray, map, '交叉路口', '/static/img/cir3.png')

}

function drawCrossRoadsMarkersOnMap(map) {

    for (var i = 0; i < cross_road_data.length; i++) {
        drawCrossRoadMarkerOnMap(cross_road_data[i], map)
    };

}

function drawCarDataOnMap(liveCarData, map) {

    var results = liveCarData;

    for (var i = 0; i < results.length; i++) {

        var color = "#3eb076" // green
        if (parseFloat(results[i].AvgOcc) > 7) {
            color = "#bb3d15"
        }

        drawLinesOnMap([aLocation(parseFloat(results[i].StartWgsY), parseFloat(results[i].StartWgsX)), aLocation(parseFloat(results[i].EndWgsY), parseFloat(results[i].EndWgsX))], map, color)
    };

}

//
function addCarsDataToGridLine(aLiveCarData) {
    var startLng = parseFloat(aLiveCarData.StartWgsY)
    var startLat = parseFloat(aLiveCarData.StartWgsX)
    var endLng = parseFloat(aLiveCarData.EndWgsY)
    var endLat = parseFloat(aLiveCarData.EndWgsX)
    classifyLine({
        lat: startLat,
        lng: startLng
    }, {
        lat: endLat,
        lng: endLng
    }, parseFloat(aLiveCarData.AvgOcc))
}

function drawConstructionSiteOnMap(constructionData, map) {

    for (var i = 0; i < constructionData.length; i++) {
        drawAMakerOnMap([constructionData[i].X, constructionData[i].Y], map, '施工地點', '/static/img/construction_small.png')
    };

}

function drawCrimeSiteOnMap(crimeData, map) {
    for (var i = 0; i < crimeData.length; i++) {
        drawAMakerOnMap([crimeData[i].lat, crimeData[i].lng], map, '常犯罪地點', '/static/img/danger_small.png')
    };

}

function drawParkOnMap(parkData, map) {
    for (var i = 0; i < parkData.length; i++) {
        drawAMakerOnMap([parkData[i].lat, parkData[i].lng], map, '公園', '')
    };
}

// ==== Get Live Data ====
function getDataFromServer() {
    console.log('get server data')
    $.get('http://localhost:3000/getdata', function(result) {
        // console.log(result)

        result = JSON.parse(result)

        var carsData = result.cars.data
        var crime = result.crime.data
        var park = result.park.data
        var constructions = result.constructions.data
        var uv = result.uv.data
        var airquality = result.airquality.data

        // console.log("carsData: " + carsData)

        // Draw all on map
        drawCarDataOnMap(carsData, map)
        drawConstructionSiteOnMap(constructions, map)
        drawCrimeSiteOnMap(crime, map)

        // Add to grid system
        for (var i = 0; i < constructions.length; i++) {
            addConstructionSiteToGrid(constructions[i])
        };

        for (var i = 0; i < crime.length; i++) {
            addCrimeSiteToGrid(crime[i])
        };

        for (var i = 0; i < carsData.length; i++) {
            addCarsDataToGridLine(carsData[i])
        };

        // console.log(JSON.stringify(grid))
    })
}

function gf(string) {
    return parseFloat(string)
}

// Type: Construction: 1, Crime: 2,
function addConstructionSiteToGrid(aConstruction) {
    classify(gf(aConstruction.X), gf(aConstruction.Y), 1)
}

function addCrimeSiteToGrid(aCrimeSiteData) {
    classify(gf(aCrimeSiteData.lat), gf(aCrimeSiteData.lng), 2)
}

function getBlockWithinDistance(distanceWithinAsKm) {

    directionsService = new google.maps.DirectionsService();
    directionsRender = new google.maps.DirectionsRenderer();

    var list = []

    var candidateLegs = []
    var currentHighestScore = 0

    for (var i = 0; i < cross_road_data.length; i++) {

        var itsDistance = calcCrow(userLocation.lat(), userLocation.lng(), parseFloat(cross_road_data[i][0]), parseFloat(cross_road_data[i][1]));

        if (itsDistance <= distanceWithinAsKm) {
            console.log('smaller')

            console.log()

            // drawAMakerOnMap([cross_road_data[i][0], cross_road_data[i][1]], map, 'Smaller', '')

            var request = {
                origin: aMapsLatLng(userLocation.lat(), userLocation.lng()),
                destination: aMapsLatLng(parseFloat(cross_road_data[i][0]), parseFloat(cross_road_data[i][1])),
                optimizeWaypoints: true,
                travelMode: google.maps.TravelMode.WALKING
            }

            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    var sublist = [];

                    var allGridsForThisLeg = []

                    for (var j = 0; j < response.routes[0].legs[0].steps.length; j++) {

                        var startPoint = response.routes[0].legs[0].steps[j].start_point;
                        var endPoint = response.routes[0].legs[0].steps[j].end_point;

                        sublist.push({
                            start: startPoint,
                            end: endPoint
                        });

                        var legGrid = getGridsThrough({
                                "lat": startPoint.G,
                                "lng": startPoint.K
                            }, {
                                "lat": endPoint.G,
                                "lng": endPoint.K
                            })
                            // console.log("legGrid step" + j + ": " + JSON.stringify(legGrid))
                            // console.log(startPoint + endPoint)

                        allGridsForThisLeg = _.union(allGridsForThisLeg, legGrid)

                    }

                    var itsScore = calculateScoreFromAllGrids(allGridsForThisLeg);

                    var scoreAndLeg = {
                        score: itsScore,
                        leg: sublist,
                        polylines: []
                    }

                    if (itsScore >= currentHighestScore) {
                        currentHighestScore = itsScore
                        console.log('Current highest score: ' + currentHighestScore)
                        // Remove all polylines
                        for (var k = 0; k < candidateLegs.length; k++) {
                            for (var h = 0; h < candidateLegs[k].polylines.length; h++) {
                                candidateLegs[k].polylines[h].setMap(null);
                            };
                        };
                    }

                    // console.log("score: " + itsScore)
                    // directionsRender.setDirections(response)

                    // Create polylines
                    for (var k = 0; k < sublist.length; k++) {
                        sublist[k]

                        var thePath = [aLocation(sublist[k].start.G, sublist[k].start.K), aLocation(sublist[k].end.G, sublist[k].end.K)]

                        var lines = new google.maps.Polyline({
                            path: thePath,
                            geodesic: true,
                            strokeColor: "#7bacfa",
                            strokeOpacity: 0.7,
                            strokeWeight: 4
                        });

                        if (itsScore == currentHighestScore) {
                            lines.setMap(map);
                        } else {
                            lines.setMap(null);
                        }

                        scoreAndLeg.polylines.push(lines)
                    };

                    console.log(scoreAndLeg)

                    candidateLegs.push(scoreAndLeg)

                    // console.log("All grid: " + allGridsForThisLeg)

                    list.push(sublist);
                    // console.log(JSON.stringify(list))
                } else {
                    console.log('Google Maps route failed ' + status)
                }
            });
        }
    };

}

function calculateScoreFromAllGrids(allGrids) {
    var finalScore = 100;
    //console.log('grid:',grid);
    //console.log('allGrids',allGrids);
    for (var i = 0; i < allGrids.length; i++) {
        var key = allGrids[i];
        if (!(key in grid)) {
            //console.log('key not found in grid')
        } else {
            var event = grid[key]["event"];
            var traffic = grid[key]["traffic"];

            var type1Count = 0;
            var type2Count = 0;
            for (var j = 0; j < event.length; j++) {
                if (event[j]["type"] == '1') {
                    type1Count++
                } else {
                    type2Count++
                }
            };

            finalScore = finalScore - (3 * type2Count) - (1 * type1Count) - (3 * traffic)
        }

        var score = grid[key]
    };
    return finalScore
}

//This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
function calcCrow(lat1, lon1, lat2, lon2) {
    var R = 6371; // km
    var dLat = toRad(lat2 - lat1);
    var dLon = toRad(lon2 - lon1);
    var lat1 = toRad(lat1);
    var lat2 = toRad(lat2);

    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return d;
}

// Converts numeric degrees to radians
function toRad(Value) {
    return Value * Math.PI / 180;
}<|endoftext|>


<commit_before>'use strict';
var chalk = require('chalk');
var _ = require('lodash');
var utils = require('keystone-utils');
var yeoman = require('yeoman-generator');

var KeystoneGenerator = yeoman.generators.Base.extend({

  initializing: function() {
    this.pkg = require('../package.json');
  },

  prompting: function() {
    var done = this.async();

    this.log('\nWelcome to the ' + chalk.green('Keystone React') + ' generator!\n');

    var prompts = [{
      type: 'input',
      name: 'projectName',
      message: 'What is the name of your project?',
      default: 'My Site'
    }, {
      type: 'confirm',
      name: 'createDirectory',
      message: 'Would you like to create a new directory for your project?',
      default: true
    }];

    this.prompt(prompts, function(props) {
      this.log('\n');
      _.extend(this, props);
      this.projectKey = utils.slug(this.projectName);
      if (props.createDirectory) {
        this.destinationRoot(this.projectKey);
      }
      done();
    }.bind(this));
  },

  keys: function keys() {
    var cookieSecretChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz!@#$%^&*()-=_+[]{}|;:",./<>?`~';
    this.cookieSecret = utils.randomString(64, cookieSecretChars);
  },

  writing: {
    project: function() {
      this.copy('keystone.js', 'keystone.js');
      this.copy('editorconfig', '.editorconfig');
      this.copy('gitignore', '.gitignore');
      this.copy('jshintrc', '.jshintrc');
      this.copy('Procfile', 'Procfile');
      this.template('_package.json', 'package.json');
    },

    clientfiles: function() {
      this.copy('client/scripts/application.js', 'client/scripts/application.js');
    },

    modelfiles: function() {
      this.copy('models/User.js', 'models/User.js');
    },

    publicfiles: function() {
      this.copy('public/favicon.ico', 'public/favicon.ico');
      this.directory('public/styles', 'public/styles');
    },

    routesfiles: function() {
      this.directory('routes/api', 'routes/api');
      this.copy('routes/index.js', 'routes/index.js');
    },

    templatefiles: function() {
      this.copy('templates/views/index.jade', 'templates/views/index.jade');
    },

    updatefiles: function() {
      this.copy('updates/0.0.1-admins.js', 'updates/0.0.1-admins.js');
    }

  },

  install: function() {
    this.log('\n' + chalk.green('Running npm install...') +
    '\n'
    );
    this.npmInstall();
  },

  end: function() {
    var cmd = (this.createDirectory ? '"cd ' + utils.slug(this.projectName) + '" then ' : '') + '"node keystone"';
    this.log(
      '\n' + chalk.green.underline('Your new project is ready!') +
      '\n' +
      '\n\nTo start Keystone, run ' + cmd + '.' +
      '\n'
    );
  }
});

module.exports = KeystoneGenerator;
<commit_msg>Porting @morenoh149's fix for secure cookie secrets<commit_after>'use strict';
var chalk = require('chalk');
var crypto = require('crypto');
var _ = require('lodash');
var utils = require('keystone-utils');
var yeoman = require('yeoman-generator');

var KeystoneGenerator = yeoman.generators.Base.extend({

  initializing: function() {
    this.pkg = require('../package.json');
  },

  prompting: function() {
    var done = this.async();

    this.log('\nWelcome to the ' + chalk.green('Keystone React') + ' generator!\n');

    var prompts = [{
      type: 'input',
      name: 'projectName',
      message: 'What is the name of your project?',
      default: 'My Site'
    }, {
      type: 'confirm',
      name: 'createDirectory',
      message: 'Would you like to create a new directory for your project?',
      default: true
    }];

    this.prompt(prompts, function(props) {
      this.log('\n');
      _.extend(this, props);
      this.projectKey = utils.slug(this.projectName);
      if (props.createDirectory) {
        this.destinationRoot(this.projectKey);
      }
      done();
    }.bind(this));
  },

  keys: function keys() {
    this.cookieSecret = crypto.randomBytes(64).toString('hex');
  },

  writing: {
    project: function() {
      this.copy('keystone.js', 'keystone.js');
      this.copy('editorconfig', '.editorconfig');
      this.copy('gitignore', '.gitignore');
      this.copy('jshintrc', '.jshintrc');
      this.copy('Procfile', 'Procfile');
      this.template('_package.json', 'package.json');
    },

    clientfiles: function() {
      this.copy('client/scripts/application.js', 'client/scripts/application.js');
    },

    modelfiles: function() {
      this.copy('models/User.js', 'models/User.js');
    },

    publicfiles: function() {
      this.copy('public/favicon.ico', 'public/favicon.ico');
      this.directory('public/styles', 'public/styles');
    },

    routesfiles: function() {
      this.directory('routes/api', 'routes/api');
      this.copy('routes/index.js', 'routes/index.js');
    },

    templatefiles: function() {
      this.copy('templates/views/index.jade', 'templates/views/index.jade');
    },

    updatefiles: function() {
      this.copy('updates/0.0.1-admins.js', 'updates/0.0.1-admins.js');
    }

  },

  install: function() {
    this.log('\n' + chalk.green('Running npm install...') +
    '\n'
    );
    this.npmInstall();
  },

  end: function() {
    var cmd = (this.createDirectory ? '"cd ' + utils.slug(this.projectName) + '" then ' : '') + '"node keystone"';
    this.log(
      '\n' + chalk.green.underline('Your new project is ready!') +
      '\n' +
      '\n\nTo start Keystone, run ' + cmd + '.' +
      '\n'
    );
  }
});

module.exports = KeystoneGenerator;
<|endoftext|>


<commit_before>/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var deleteDuplicates = function(head) {
  var hash = new Set();
  var current = head;
  var pre = null;

  while (current) {
    var val = current.val;

    if (hash.has(val)) {
      pre.next = current.next;
    } else {
      pre = current;
      hash.add(val);
      console.log(hash.keys(), val)
    }

    current = current.next;
  }

  console.log(hash.values())
};

var eq = require('assert').deepEqual;
var nodeList = require('./_util').nodeList;

var l = nodeList.create([1, 2, 2, 1, 3]);
deleteDuplicates(l);
eq(nodeList.toArray(l), [1,2,3]);
<commit_msg>Remove Duplicates from Sorted List: O(n) space solution<commit_after>/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var deleteDuplicates = function(head) {
  var hash = new Set();
  var current = head;
  var pre = null;

  while (current) {
    var val = current.val;

    if (hash.has(val)) {
      pre.next = current.next;
    } else {
      pre = current;
      hash.add(val);
    }

    current = current.next;
  }

  return head;
};

var eq = require('assert').deepEqual;
var nodeList = require('./_util').nodeList;
var l;

l = nodeList.create([1, 2, 2, 1, 3]);
eq(nodeList.toArray(deleteDuplicates(l)), [1,2,3]);

l = nodeList.create([1, 1]);
eq(nodeList.toArray(deleteDuplicates(l)), [1]);
l = nodeList.create([]);
eq(nodeList.toArray(deleteDuplicates(l)), []);
<|endoftext|>