<commit_before>var lrSnippet = require('connect-livereload')();

var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

module.exports = function (grunt) {
    // log task running time
    require('time-grunt')(grunt);

    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var pathConfig = {
        app: 'app',
        dist: 'dist',
        tmp: '.tmp',
        test: 'test'
    };

    grunt.initConfig({
        paths: pathConfig,
        watch: {
            compass: {
                files: ['<%= paths.app %>/compass/**/*'],
                tasks: ['compass:server']
            },
            test: {
                files: ['<%= paths.app %>/javascripts/**/*.js'],
                tasks: ['newer:jshint:test', 'karma:server:run'],
                options: {
                    spawn: false
                }
            },
            livereload: {
                files: [
                    '<%= paths.app %>/**/*.html',
                    '<%= paths.app %>/javascripts/**/*.js',
                    '<%= paths.app %>/images/**/*',
                    '<%= paths.tmp %>/stylesheets/**/*.css',
                    '<%= paths.tmp %>/images/**/*'
                ],
                options: {
                    livereload: true,
                    spawn: false
                }
            },
            configFiles: {
                files: ['Gruntfile.js'],
                options: {
                    reload: true
                }
            }
        },
        connect: {
            options: {
                port: 9999,
                hostname: '0.0.0.0'
            },
            server: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, pathConfig.tmp),
                            mountFolder(connect, pathConfig.app)
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://127.0.0.1:<%= connect.options.port %>',
                app: 'Google Chrome Canary'
            }
        },
        clean: {
            dist: ['<%= paths.tmp %>', '<%= paths.dist %>'],
            server: '<%= paths.tmp %>'
        },
        useminPrepare: {
            html: ['<%= paths.app %>/**/*.html'],
            options: {
                dest: '<%= paths.dist %>'
            }
        },
        usemin: {
            html: ['<%= paths.dist %>/**/*.html'],
            css: ['<%= paths.dist %>/stylesheets/**/*.css'],
            options: {
                dirs: ['<%= paths.dist %>'],
                assetsDirs: ['<%= paths.dist %>']
            }
        },
        htmlmin: {
            options: {
                collapseWhitespace: true
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= paths.dist %>',
                    src: ['**/*.html'],
                    dest: '<%= paths.dist %>'
                }]
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.app %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        '**/*.html',
                        '!components/**/*.html',
                        '!compass/**/*.html',
                        'images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf,svg}'
                    ]
                }]
            },
            html: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.tmp %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        '**/*.html'
                    ]
                }]
            },
            compass: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.tmp %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        'images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf,svg}'
                    ]
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= paths.app %>/compass/sass',
                imagesDir: '<%= paths.app %>/compass/images',
                fontsDir: '<%= paths.app %>/images/fonts',
                relativeAssets: true
            },
            dist: {
                options: {
                    cssDir: '<%= paths.dist %>/stylesheets',
                    generatedImagesDir: '<%= paths.tmp %>/images',
                    httpGeneratedImagesPath: '/images/',
                    outputStyle: 'compressed',
                    environment: 'production',
                    relativeAssets: false
                }
            },
            server: {
                options: {
                    cssDir: '<%= paths.tmp %>/stylesheets',
                    generatedImagesDir: '<%= paths.tmp %>/images',
                    debugInfo: true,
                    environment: 'development'
                }
            }
        },
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= paths.dist %>/javascripts/**/*.js',
                        '<%= paths.dist %>/stylesheets/**/*.css',
                        '<%= paths.dist %>/images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf}'
                    ]
                }
            }
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= paths.dist %>/images',
                    src: '**/*.{png,jpg,jpeg}',
                    dest: '<%= paths.dist %>/images'
                }]
            }
        },
        requirejs: {
            dist: {
                options: {
                    optimize: 'uglify',
                    uglify: {
                        toplevel: true,
                        ascii_only: false,
                        beautify: false
                    },
                    preserveLicenseComments: true,
                    useStrict: false,
                    wrap: true
                }
            }
        },
        concurrent: {
            server: {
                tasks: ['clean:server', 'compass:server'],
                options: {
                    logConcurrentOutput: true
                }
            },
            dist: {
                tasks: ['copy:dist', 'compass:dist'],
                options: {
                    logConcurrentOutput: true
                }
            }
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            test: ['<%= paths.app %>/javascripts/**/*.js']
        },
        karma: {
            options: {
                configFile: '<%= paths.test %>/karma.conf.js',
                browsers: ['Chrome_without_security']
            },
            server: {
                reporters: ['progress'],
                background: true
            },
            test: {
                reporters: ['progress', 'junit', 'coverage'],
                preprocessors: {
                    '<%= paths.app %>/javascripts/**/*.js' : 'coverage'
                },
                junitReporter: {
                    outputFile: '<%= paths.test %>/output/test-results.xml'
                },
                coverageReporter: {
                    type: 'html',
                    dir: '<%= paths.test %>/output/coverage/'
                },
                singleRun: true
            },
            travis: {
                browsers: ['PhantomJS'],
                reporters: ['progress'],
                singleRun: true
            }
        },
        bump: {
            options: {
                files: ['package.json', 'bower.json'],
                updateConfigs: [],
                commit: true,
                commitMessage: 'Release v%VERSION%',
                commitFiles: ['-a'],
                createTag: true,
                tagName: 'v%VERSION%',
                tagMessage: 'Version %VERSION%',
                push: false
            }
        },
        cdn: {
            options: {
                flatten: true
            },
            dist: {
                options: {
                    cdn: 'http://static.wdjimg.com/xxx',
                },
                src: ['<%= paths.dist %>/**/*.html', '<%= paths.dist %>/**/*.css']
            },
            staging: {
                options: {
                    cdn: 'https://s3.cn-north-1.amazonaws.com.cn/web-statics-staging/xxx',
                },
                src: ['<%= paths.dist %>/**/*.html', '<%= paths.dist %>/**/*.css']
            }
        },
        aws_s3: {
            options: {
                accessKeyId: '',
                secretAccessKey: '',
                region: 'cn-north-1',
                uploadConcurrency: 5,
                signatureVersion: 'v4'
            },
            staging: {
                options: {
                    bucket: 'web-statics-staging',
                    differential: true,
                    params: {
                        CacheControl: '31536000'
                    }
                },
                files: [{
                    expand: true,
                    cwd: 'dist',
                    src: ['**', '!**/*.css', '!**/*.js'],
                    dest: 'xxx/'

                }, {
                    expand: true,
                    cwd: 'gzip',
                    src: ['**'],
                    dest: 'xxx/',
                    params: {
                        ContentEncoding: 'gzip'
                    }
                }]
            },
            production: {
                options: {
                    bucket: 'web-statics-production',
                    differential: true,
                    params: {
                        CacheControl: '31536000'
                    }
                },
                files: [{
                    expand: true,
                    cwd: 'dist',
                    src: ['**', '!**/*.css', '!**/*.js'],
                    dest: 'xxx/'
                }, {
                    expand: true,
                    cwd: 'gzip',
                    src: ['**'],
                    dest: 'xxx/',
                    params: {
                        ContentEncoding: 'gzip'
                    }
                }]
            }
        },
        compress: {
            js: {
                options: {
                    mode: 'gzip'
                },
                expand: true,
                cwd: 'dist/',
                src: ['**/*.js'],
                dest: 'gzip/',
                ext: '.js'
            },
            css: {
                options: {
                    mode: 'gzip'
                },
                expand: true,
                cwd: 'dist/',
                src: ['**/*.css'],
                dest: 'gzip/',
                ext: '.css'
            }
        }
    });

    grunt.registerTask('serve', [
        'concurrent:server',
        'connect:server',
        'karma:server',
        'open',
        'watch'
    ]);

    grunt.registerTask('test', [
        'jshint:test',
        'karma:test'
    ]);

    grunt.registerTask('test:travis', [
        'jshint:test',
        'karma:travis'
    ]);

    grunt.registerTask('build:staging', [
        'clean:dist',
        'concurrent:dist',
        'useminPrepare',
        'concat',
        'uglify',
        // 'cssmin', // Uncomment this line if using none-sass style
        // 'requirejs:dist', // Uncomment this line if using RequireJS in your project
        'rev',
        'copy:compass',
        'imagemin',
        'usemin',
        'htmlmin',
        'cdn:staging',
        'compress:js',
        'compress:css',
        'aws_s3:staging'
    ]);

    grunt.registerTask('build:production', [
        'clean:dist',
        'concurrent:dist',
        'useminPrepare',
        'concat',
        'uglify',
        // 'cssmin', // Uncomment this line if using none-sass style
        // 'requirejs:dist', // Uncomment this line if using RequireJS in your project
        'rev',
        'copy:compass',
        'imagemin',
        'usemin',
        'htmlmin',
        'cdn:dist',
        'compress:js',
        'compress:css',
        'aws_s3:production'
    ]);

    grunt.registerTask(['update'], [
        'bump-only:patch',
        'changelog',
        'bump-commit'
    ]);

    grunt.registerTask(['update:minor'], [
        'bump-only:minor',
        'changelog',
        'bump-commit'
    ]);

    grunt.registerTask(['update:major'], [
        'bump-only:major',
        'changelog',
        'bump-commit'
    ]);
};
<commit_msg>Update _Gruntfile.js<commit_after>var lrSnippet = require('connect-livereload')();

var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

module.exports = function (grunt) {
    // log task running time
    require('time-grunt')(grunt);

    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var pathConfig = {
        app: 'app',
        dist: 'dist',
        tmp: '.tmp',
        test: 'test'
    };

    grunt.initConfig({
        paths: pathConfig,
        watch: {
            compass: {
                files: ['<%= paths.app %>/compass/**/*'],
                tasks: ['compass:server']
            },
            test: {
                files: ['<%= paths.app %>/javascripts/**/*.js'],
                tasks: ['newer:jshint:test', 'karma:server:run'],
                options: {
                    spawn: false
                }
            },
            livereload: {
                files: [
                    '<%= paths.app %>/**/*.html',
                    '<%= paths.app %>/javascripts/**/*.js',
                    '<%= paths.app %>/images/**/*',
                    '<%= paths.tmp %>/stylesheets/**/*.css',
                    '<%= paths.tmp %>/images/**/*'
                ],
                options: {
                    livereload: true,
                    spawn: false
                }
            },
            configFiles: {
                files: ['Gruntfile.js'],
                options: {
                    reload: true
                }
            }
        },
        connect: {
            options: {
                port: 9999,
                hostname: '0.0.0.0'
            },
            server: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, pathConfig.tmp),
                            mountFolder(connect, pathConfig.app)
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://127.0.0.1:<%= connect.options.port %>',
                app: 'Google Chrome Canary'
            }
        },
        clean: {
            dist: ['<%= paths.tmp %>', '<%= paths.dist %>'],
            server: '<%= paths.tmp %>'
        },
        useminPrepare: {
            html: ['<%= paths.app %>/**/*.html'],
            options: {
                dest: '<%= paths.dist %>'
            }
        },
        usemin: {
            html: ['<%= paths.dist %>/**/*.html'],
            css: ['<%= paths.dist %>/stylesheets/**/*.css'],
            options: {
                dirs: ['<%= paths.dist %>'],
                assetsDirs: ['<%= paths.dist %>']
            }
        },
        htmlmin: {
            options: {
                collapseWhitespace: true
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= paths.dist %>',
                    src: ['**/*.html'],
                    dest: '<%= paths.dist %>'
                }]
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.app %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        '**/*.html',
                        '!components/**/*.html',
                        '!compass/**/*.html',
                        'images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf,svg}'
                    ]
                }]
            },
            html: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.tmp %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        '**/*.html'
                    ]
                }]
            },
            compass: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= paths.tmp %>',
                    dest: '<%= paths.dist %>',
                    src: [
                        'images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf,svg}'
                    ]
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= paths.app %>/compass/sass',
                imagesDir: '<%= paths.app %>/compass/images',
                fontsDir: '<%= paths.app %>/images/fonts',
                relativeAssets: true
            },
            dist: {
                options: {
                    cssDir: '<%= paths.dist %>/stylesheets',
                    generatedImagesDir: '<%= paths.tmp %>/images',
                    httpGeneratedImagesPath: '/images/',
                    outputStyle: 'compressed',
                    environment: 'production',
                    relativeAssets: false
                }
            },
            server: {
                options: {
                    cssDir: '<%= paths.tmp %>/stylesheets',
                    generatedImagesDir: '<%= paths.tmp %>/images',
                    debugInfo: true,
                    environment: 'development'
                }
            }
        },
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= paths.dist %>/javascripts/**/*.js',
                        '<%= paths.dist %>/stylesheets/**/*.css',
                        '<%= paths.dist %>/images/**/*.{webp,gif,png,jpg,jpeg,ttf,otf}'
                    ]
                }
            }
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= paths.dist %>/images',
                    src: '**/*.{png,jpg,jpeg}',
                    dest: '<%= paths.dist %>/images'
                }]
            }
        },
        requirejs: {
            dist: {
                options: {
                    optimize: 'uglify',
                    uglify: {
                        toplevel: true,
                        ascii_only: false,
                        beautify: false
                    },
                    preserveLicenseComments: true,
                    useStrict: false,
                    wrap: true
                }
            }
        },
        concurrent: {
            server: {
                tasks: ['clean:server', 'compass:server'],
                options: {
                    logConcurrentOutput: true
                }
            },
            dist: {
                tasks: ['copy:dist', 'compass:dist'],
                options: {
                    logConcurrentOutput: true
                }
            }
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            test: ['<%= paths.app %>/javascripts/**/*.js']
        },
        karma: {
            options: {
                configFile: '<%= paths.test %>/karma.conf.js',
                browsers: ['Chrome_without_security']
            },
            server: {
                reporters: ['progress'],
                background: true
            },
            test: {
                reporters: ['progress', 'junit', 'coverage'],
                preprocessors: {
                    '<%= paths.app %>/javascripts/**/*.js' : 'coverage'
                },
                junitReporter: {
                    outputFile: '<%= paths.test %>/output/test-results.xml'
                },
                coverageReporter: {
                    type: 'html',
                    dir: '<%= paths.test %>/output/coverage/'
                },
                singleRun: true
            },
            travis: {
                browsers: ['PhantomJS'],
                reporters: ['progress'],
                singleRun: true
            }
        },
        bump: {
            options: {
                files: ['package.json', 'bower.json'],
                updateConfigs: [],
                commit: true,
                commitMessage: 'Release v%VERSION%',
                commitFiles: ['-a'],
                createTag: true,
                tagName: 'v%VERSION%',
                tagMessage: 'Version %VERSION%',
                push: false
            }
        },
        cdn: {
            options: {
                flatten: true
            },
            dist: {
                options: {
                    cdn: 'http://static.wdjimg.com/xxx',
                },
                src: ['<%= paths.dist %>/**/*.html', '<%= paths.dist %>/**/*.css']
            },
            staging: {
                options: {
                    cdn: 'https://s3.cn-north-1.amazonaws.com.cn/web-statics-staging/xxx',
                },
                src: ['<%= paths.dist %>/**/*.html', '<%= paths.dist %>/**/*.css']
            }
        },
        'aws_s3': {
            options: {
                accessKeyId: '',
                secretAccessKey: '',
                region: 'cn-north-1',
                uploadConcurrency: 5,
                signatureVersion: 'v4'
            },
            staging: {
                options: {
                    bucket: 'web-statics-staging',
                    differential: true,
                    params: {
                        CacheControl: '31536000'
                    }
                },
                files: [{
                    expand: true,
                    cwd: 'dist',
                    src: ['**', '!**/*.css', '!**/*.js'],
                    dest: 'xxx/'

                }, {
                    expand: true,
                    cwd: 'gzip',
                    src: ['**'],
                    dest: 'xxx/',
                    params: {
                        ContentEncoding: 'gzip'
                    }
                }]
            },
            production: {
                options: {
                    bucket: 'web-statics-production',
                    differential: true,
                    params: {
                        CacheControl: '31536000'
                    }
                },
                files: [{
                    expand: true,
                    cwd: 'dist',
                    src: ['**', '!**/*.css', '!**/*.js'],
                    dest: 'xxx/'
                }, {
                    expand: true,
                    cwd: 'gzip',
                    src: ['**'],
                    dest: 'xxx/',
                    params: {
                        ContentEncoding: 'gzip'
                    }
                }]
            }
        },
        compress: {
            js: {
                options: {
                    mode: 'gzip'
                },
                expand: true,
                cwd: 'dist/',
                src: ['**/*.js'],
                dest: 'gzip/',
                ext: '.js'
            },
            css: {
                options: {
                    mode: 'gzip'
                },
                expand: true,
                cwd: 'dist/',
                src: ['**/*.css'],
                dest: 'gzip/',
                ext: '.css'
            }
        }
    });

    grunt.registerTask('serve', [
        'concurrent:server',
        'connect:server',
        'karma:server',
        'open',
        'watch'
    ]);

    grunt.registerTask('test', [
        'jshint:test',
        'karma:test'
    ]);

    grunt.registerTask('test:travis', [
        'jshint:test',
        'karma:travis'
    ]);

    grunt.registerTask('build:staging', [
        'clean:dist',
        'concurrent:dist',
        'useminPrepare',
        'concat',
        'uglify',
        // 'cssmin', // Uncomment this line if using none-sass style
        // 'requirejs:dist', // Uncomment this line if using RequireJS in your project
        'rev',
        'copy:compass',
        'imagemin',
        'usemin',
        'htmlmin',
        'cdn:staging',
        'compress:js',
        'compress:css',
        'aws_s3:staging'
    ]);

    grunt.registerTask('build:production', [
        'clean:dist',
        'concurrent:dist',
        'useminPrepare',
        'concat',
        'uglify',
        // 'cssmin', // Uncomment this line if using none-sass style
        // 'requirejs:dist', // Uncomment this line if using RequireJS in your project
        'rev',
        'copy:compass',
        'imagemin',
        'usemin',
        'htmlmin',
        'cdn:dist',
        'compress:js',
        'compress:css',
        'aws_s3:production'
    ]);

    grunt.registerTask(['update'], [
        'bump-only:patch',
        'changelog',
        'bump-commit'
    ]);

    grunt.registerTask(['update:minor'], [
        'bump-only:minor',
        'changelog',
        'bump-commit'
    ]);

    grunt.registerTask(['update:major'], [
        'bump-only:major',
        'changelog',
        'bump-commit'
    ]);
};
<|endoftext|>


<commit_before>class JAMS {
	constructor (config) {
		// stuff
		this.moduleCounter	= 0;
		this.modules 		= [];
		this.midiModules 	= [];

		this.preferences	= new ApplicationPreference();
		this.g				= new Graphics({width: config.width, height: config.height, font: font}); //font exists because
		this.interface		= new Interface(this.g);
		this.desktop		= new Desktop(this.g, this.modules);
		this.mouseListeners = new ListenerList(this.g.DOMElement, ["mousedown", "mouseup", "mousemove"]);
		this.keyListeners	= new ListenerList(this.g.DOMElement, ["keydown"]);

		// Audio
		this.aC = (config.audioContext instanceof AudioContext)? config.audioContext : new AudioContext();
		window.sampleRate = this.aC.sampleRate;
		this.processor = this.aC.createScriptProcessor(this.preferences.getItem("bufferSize"), 0, 2);
		let splitter	= this.aC.createChannelSplitter();
		let merger		= this.aC.createChannelMerger();

		this.processor.connect(splitter);
		splitter.connect(merger, 0 , 0);
		splitter.connect(merger, 1 , 1);
		merger.connect(this.aC.destination);

		this.t = 0;
		this.frameCount = 0;

		this.outputModule = this.createModule(~~(innerWidth/2), ~~(innerHeight/2), Modules.Output);
		this.interface.add(new InterfaceMenuBar({menus : JAMS.Interactions.menuBarMenus, app: this}));

		//plugins
		this.plugins = [{
			name : "Oscillators",
			children: ["SineOSC"]
		},{
			name : "Math",
			children: ["Number", "Plus", "Multiplier", "Remainder", "Rand"]
		},{
			name : "Clock",
			children: ["Clock", "ClockDivider"]
		},{
			name : "Harmony",
			children: ["Note2Freq"]
		},{
			name: "Sequencers",
			children: ["Sequencer16", "Switch"]
		},{
			name: "Envelopes",
			children: ["LinearAD"]
		},{
			name: "Sampling",
			children: ["Sampler"]
		},{
			name: "Effects",
			children: ["Flange", "Delay"]
		},{
			name: "Misc",
			children: ["QuadMixer", "Scope", "XYScope", "Readout", "TextDisplay", "MonoMerge"]
		}];
	}

	appendTo	(element) {
		this.g.appendTo(element);
		return this;
	}

	init 		() {
		let _ = this;

		this.processor.onaudioprocess = function(e) {
			let obuffer = e.outputBuffer;
			let incr = obuffer.length/_.aC.sampleRate;

			let ldata = obuffer.getChannelData(0);
			let rdata = obuffer.getChannelData(1);

			for (let i = 0; i < obuffer.length; i++) {
				let o = _.audioLoop(_.t + (i/_.aC.sampleRate));
				ldata[i] = o[0];
				rdata[i] = o[1];
			}

			_.t += incr;
		}

		// MIDI Error Window
		let mid = new MIDI(error => {
			this.alert("Your browser does not support MIDI");
		});

		mid.on('any', (a,e) => {
			this.midiModules.forEach( mod => {
				mod.setParam(mod.midiParam, e.data);
			})
		})

		// make DOM focus-able
		this.g.DOMElement.tabIndex = 1; // oh gosh (what does this do?)
		// okay i spent 30 minutes trying to figure out why keydown doesn't work. so this line is the thing.

		// zooming
		this.g.DOMElement.addEventListener("wheel", e => { e.preventDefault();
			if(e.ctrlKey) {
				if(e.deltaY < 0)
					this.desktop.scaleUp(e)
				else
					this.desktop.scaleDown(e);
			}
		})

		this.mouseListeners.add("mousedown"	, this.interface.eMouseDown			, this.interface);
		this.mouseListeners.add("mousemove"	, this.interface.eMouseMove			, this.interface);
		this.mouseListeners.add("mouseup"	, this.interface.eMouseUp			, this.interface);
		this.mouseListeners.add("mousedown"	, this.desktop.eMouseDown			, this.desktop);
		this.mouseListeners.add("mousemove"	, this.desktop.eDrag				, this.desktop, false);
		this.mouseListeners.add("mousemove"	, this.desktop.eMouseMove			, this.desktop);
		this.mouseListeners.add("mousemove"	, this.desktop.eModuleDrag			, this.desktop, false);
		this.mouseListeners.add("mousemove"	, this.desktop.eModuleShiftDrag		, this.desktop, false);
		this.mouseListeners.add("mouseup"	, this.desktop.eMouseUp				, this.desktop);

		this.keyListeners.add("keydown"		, this.interface.eKeyDown			, this.interface);
		this.keyListeners.add("keydown"		, this.desktop.eKeyDown				, this.desktop);

		// rightclick
		this.g.DOMElement.addEventListener("contextmenu", this.eContextMenu.bind(this));

		// fire rendering loop
		this.render();
	}

	eContextMenu(e) {
		e.preventDefault();
		const x = e.clientX;
		const y = e.clientY;

		let currentModule = this.desktop.isOnModule(x, y);

		if (currentModule) {

			let currentInput = this.desktop.isOnInput(currentModule, x, y);

			if (currentInput !== -1) {
				this.interface.add(
					new InterfaceContextMenu({ x: x, y: y,
						options: [{
							text: "Disconnect",
							callback: () => currentModule.unsetInput(currentInput)
						}]
					})
				)
			} else {
				// for some reason, passing `this` doesn't work, so we pass it as an argument
				JAMS.Interactions.rightClickOnModule.call(null, this, e, x, y, currentModule);
			}
		} else {
			JAMS.Interactions.rightClickOnDesktop.call(null, this, e, x, y);
		}
	}

	render 		() {
		if (this.frameCount % ~~this.preferences.getItem("fpsFactor") == 0) {
			this.g.background(this.preferences.getItem("background"));
			this.desktop.render();
			this.interface.render();
		}
		this.frameCount = (this.frameCount + 1) % 9999;
		requestAnimationFrame(this.render.bind(this));
	}

	audioLoop	(t) {
		this.modules.forEach( module => {
			if(module.prerun == true) module.run(t);
		});

		return this.outputModule.run(t, 1, 0);
	}

	createModule(x, y, module, id) {
		var mod = new module({
			id: (id)? id : ++this.moduleCounter,
			x: x,
			y: y
		});

		if(mod.midiRequest == true) this.midiModules.push(mod);
		this.modules.push(mod);
		return mod;
	}

	deleteModule(deletingModule) {
		let i = 0, _ = this;

		this.midiModules.some( (module, index) => {
			if(module == deletingModule) {
				_.midiModules.splice(index, 1);
				return true;
			}
		})

		this.modules.forEach( (module, id) => {
			if( module == deletingModule ) i = id;
			module.inputs.forEach( (input, index) => {
				if( !input ) return;
				if( input.module == deletingModule ) module.unsetInput(index);
			});
		});
		this.modules.splice(i, 1);
	}

	getModuleFromId 	(id) {
		var mod; this.modules.some( m => (mod = m).id == id );
		if(mod.id !== id) return undefined;
		return mod;
	}

	newSetup() {
		this.modules.splice(0,this.modules.length);
		this.outputModule = this.createModule(innerWidth/2, innerHeight/2, Modules.Output);
	}

	exportSetup		() {
		let fileName = "";
		this.interface
		.add(
			(new InterfaceWindow({
				title: "Save Setup", x: ~~(innerWidth/2), y: ~~(innerHeight/2), w: 200, h: 100,
				isResizable: false
			}))
			.appendChild(
				new WindowText({ content: "FILENAME", ww: 1/2, wh: 50 })
			)
			.appendChild(
				new WindowTextField({ ww: 1/2, wh: 50,
					setValue: x => { fileName = x },
					getValue: () => fileName
				})
			)
			.appendChild(
				new WindowButton({ ww: 1 , wh: 20,
					content: "SAVE",
					callback: () => {
						saveAs(new File([this.saveSetupToJSON()], "JAMS-"+fileName+".json", {type: "data:application/json;charset=utf-8"}));
					}
				})
			)
		)
	}

	openSetup() {
		setTimeout(() => { /**remove canvas drag listener**/ },100);
		var opener = document.createElement("input");
		opener.type = "file";
		opener.accept = ".json";
		opener.addEventListener('change', (e) => {
			if(!e.target.files[0] || e.target.files[0].name.substr(-5).toLowerCase() !== ".json") return;
			var reader = new FileReader();
			reader.onload = (e) => {
				this.loadSetup(e.target.result);
			}
			reader.readAsText(e.target.files[0]);

		});
		opener.click();
	}

	openSetupFromUrl (url) {
		let win = alert("Loading Setup...");
		fetch(url).then(response => {
			if (response.ok)
				return response.text()
			this.alert("Failed loading setup from URL");
		}).then(data => {
			this.loadSetup(data);
			win.close();
		});
	}

	alert 		(message, title = "Alert") { //this is synonymous to window.alert of the DOM
		let win = new InterfaceWindow({
				x: ~~(innerWidth/2), y: ~~(innerHeight/2),
				w: 370, h: 100,
				title: title
			});

			win
			.appendChild(new WindowText({
				ww: 1, wh: 30,
				content: message,
				fontSize: 1
			}))
			.appendChild(new WindowButton({
				ww: 1, wh: 30,
				content: "OK!",
				fontSize: 1,
				callback: () => win.close()
			}));

			this.interface.add(win);
		return win;
	}

	saveSetupToJSON() {
		var setup = [];
		this.modules.forEach( module => {
			var inputsArr = [];
			module.inputs.forEach( (input,ind) => {
				inputsArr[ind] = {
					id : input.id,
					index : input.index
				}
			});

			let params = module.params.map( p => {
				if (!p.paramSave) {
					return p.value;
				} else {
					return p.paramSave(p.value);
				}
			});

			setup.push({
				id: module.id,
				type: module.className,
				x: module.x,
				y: module.y,
				inputs: inputsArr,
				params: params,
				name: module.name
			})
		});
		return JSON.stringify(setup);
	}

	loadSetup		(json) {
		let _ = this;
		this.newSetup();
		let setup = JSON.parse(json);
		try {
			setup.forEach( module => {
				_.moduleCounter = Math.max(_.moduleCounter, module.id);
				try {
					var mod = _.createModule(module.x, module.y, Modules[module.type], module.id);
				} catch(e) {
					console.warn(e);
					module.invalid = true;
					console.warn("Possible that " + module.type + " is not a valid module");
					return;
				}
				mod.name = module.name || "";
				module.params.forEach( (val, ind) => {
						if(!mod.params[ind].paramLoad)
							mod.setParam(ind, val);
						else
							mod.setParam(ind, mod.params[ind].paramLoad(val));
				});

				if(module.type == "Output") {
					_.deleteModule(_.outputModule);
					_.outputModule = mod;
				}
			})
			setup.forEach( module => {
				let targetModule = _.getModuleFromId(module.id);
				if(targetModule == undefined) return;
				module.inputs.forEach( (input,index) => {
					if( input == null ) return;
					let sourceModule = _.getModuleFromId(input.id);
					if( sourceModule == undefined ) return;
					sourceModule.connect(targetModule, index, input.index);
				})
			});
		} catch(e) {
			console.error("Corrupted Setup File: ", e); return;
		}
	}

}<commit_msg>ugh. wrong alert<commit_after>class JAMS {
	constructor (config) {
		// stuff
		this.moduleCounter	= 0;
		this.modules 		= [];
		this.midiModules 	= [];

		this.preferences	= new ApplicationPreference();
		this.g				= new Graphics({width: config.width, height: config.height, font: font}); //font exists because
		this.interface		= new Interface(this.g);
		this.desktop		= new Desktop(this.g, this.modules);
		this.mouseListeners = new ListenerList(this.g.DOMElement, ["mousedown", "mouseup", "mousemove"]);
		this.keyListeners	= new ListenerList(this.g.DOMElement, ["keydown"]);

		// Audio
		this.aC = (config.audioContext instanceof AudioContext)? config.audioContext : new AudioContext();
		window.sampleRate = this.aC.sampleRate;
		this.processor = this.aC.createScriptProcessor(this.preferences.getItem("bufferSize"), 0, 2);
		let splitter	= this.aC.createChannelSplitter();
		let merger		= this.aC.createChannelMerger();

		this.processor.connect(splitter);
		splitter.connect(merger, 0 , 0);
		splitter.connect(merger, 1 , 1);
		merger.connect(this.aC.destination);

		this.t = 0;
		this.frameCount = 0;

		this.outputModule = this.createModule(~~(innerWidth/2), ~~(innerHeight/2), Modules.Output);
		this.interface.add(new InterfaceMenuBar({menus : JAMS.Interactions.menuBarMenus, app: this}));

		//plugins
		this.plugins = [{
			name : "Oscillators",
			children: ["SineOSC"]
		},{
			name : "Math",
			children: ["Number", "Plus", "Multiplier", "Remainder", "Rand"]
		},{
			name : "Clock",
			children: ["Clock", "ClockDivider"]
		},{
			name : "Harmony",
			children: ["Note2Freq"]
		},{
			name: "Sequencers",
			children: ["Sequencer16", "Switch"]
		},{
			name: "Envelopes",
			children: ["LinearAD"]
		},{
			name: "Sampling",
			children: ["Sampler"]
		},{
			name: "Effects",
			children: ["Flange", "Delay"]
		},{
			name: "Misc",
			children: ["QuadMixer", "Scope", "XYScope", "Readout", "TextDisplay", "MonoMerge"]
		}];
	}

	appendTo	(element) {
		this.g.appendTo(element);
		return this;
	}

	init 		() {
		let _ = this;

		this.processor.onaudioprocess = function(e) {
			let obuffer = e.outputBuffer;
			let incr = obuffer.length/_.aC.sampleRate;

			let ldata = obuffer.getChannelData(0);
			let rdata = obuffer.getChannelData(1);

			for (let i = 0; i < obuffer.length; i++) {
				let o = _.audioLoop(_.t + (i/_.aC.sampleRate));
				ldata[i] = o[0];
				rdata[i] = o[1];
			}

			_.t += incr;
		}

		// MIDI Error Window
		let mid = new MIDI(error => {
			this.alert("Your browser does not support MIDI");
		});

		mid.on('any', (a,e) => {
			this.midiModules.forEach( mod => {
				mod.setParam(mod.midiParam, e.data);
			})
		})

		// make DOM focus-able
		this.g.DOMElement.tabIndex = 1; // oh gosh (what does this do?)
		// okay i spent 30 minutes trying to figure out why keydown doesn't work. so this line is the thing.

		// zooming
		this.g.DOMElement.addEventListener("wheel", e => { e.preventDefault();
			if(e.ctrlKey) {
				if(e.deltaY < 0)
					this.desktop.scaleUp(e)
				else
					this.desktop.scaleDown(e);
			}
		})

		this.mouseListeners.add("mousedown"	, this.interface.eMouseDown			, this.interface);
		this.mouseListeners.add("mousemove"	, this.interface.eMouseMove			, this.interface);
		this.mouseListeners.add("mouseup"	, this.interface.eMouseUp			, this.interface);
		this.mouseListeners.add("mousedown"	, this.desktop.eMouseDown			, this.desktop);
		this.mouseListeners.add("mousemove"	, this.desktop.eDrag				, this.desktop, false);
		this.mouseListeners.add("mousemove"	, this.desktop.eMouseMove			, this.desktop);
		this.mouseListeners.add("mousemove"	, this.desktop.eModuleDrag			, this.desktop, false);
		this.mouseListeners.add("mousemove"	, this.desktop.eModuleShiftDrag		, this.desktop, false);
		this.mouseListeners.add("mouseup"	, this.desktop.eMouseUp				, this.desktop);

		this.keyListeners.add("keydown"		, this.interface.eKeyDown			, this.interface);
		this.keyListeners.add("keydown"		, this.desktop.eKeyDown				, this.desktop);

		// rightclick
		this.g.DOMElement.addEventListener("contextmenu", this.eContextMenu.bind(this));

		// fire rendering loop
		this.render();
	}

	eContextMenu(e) {
		e.preventDefault();
		const x = e.clientX;
		const y = e.clientY;

		let currentModule = this.desktop.isOnModule(x, y);

		if (currentModule) {

			let currentInput = this.desktop.isOnInput(currentModule, x, y);

			if (currentInput !== -1) {
				this.interface.add(
					new InterfaceContextMenu({ x: x, y: y,
						options: [{
							text: "Disconnect",
							callback: () => currentModule.unsetInput(currentInput)
						}]
					})
				)
			} else {
				// for some reason, passing `this` doesn't work, so we pass it as an argument
				JAMS.Interactions.rightClickOnModule.call(null, this, e, x, y, currentModule);
			}
		} else {
			JAMS.Interactions.rightClickOnDesktop.call(null, this, e, x, y);
		}
	}

	render 		() {
		if (this.frameCount % ~~this.preferences.getItem("fpsFactor") == 0) {
			this.g.background(this.preferences.getItem("background"));
			this.desktop.render();
			this.interface.render();
		}
		this.frameCount = (this.frameCount + 1) % 9999;
		requestAnimationFrame(this.render.bind(this));
	}

	audioLoop	(t) {
		this.modules.forEach( module => {
			if(module.prerun == true) module.run(t);
		});

		return this.outputModule.run(t, 1, 0);
	}

	createModule(x, y, module, id) {
		var mod = new module({
			id: (id)? id : ++this.moduleCounter,
			x: x,
			y: y
		});

		if(mod.midiRequest == true) this.midiModules.push(mod);
		this.modules.push(mod);
		return mod;
	}

	deleteModule(deletingModule) {
		let i = 0, _ = this;

		this.midiModules.some( (module, index) => {
			if(module == deletingModule) {
				_.midiModules.splice(index, 1);
				return true;
			}
		})

		this.modules.forEach( (module, id) => {
			if( module == deletingModule ) i = id;
			module.inputs.forEach( (input, index) => {
				if( !input ) return;
				if( input.module == deletingModule ) module.unsetInput(index);
			});
		});
		this.modules.splice(i, 1);
	}

	getModuleFromId 	(id) {
		var mod; this.modules.some( m => (mod = m).id == id );
		if(mod.id !== id) return undefined;
		return mod;
	}

	newSetup() {
		this.modules.splice(0,this.modules.length);
		this.outputModule = this.createModule(innerWidth/2, innerHeight/2, Modules.Output);
	}

	exportSetup		() {
		let fileName = "";
		this.interface
		.add(
			(new InterfaceWindow({
				title: "Save Setup", x: ~~(innerWidth/2), y: ~~(innerHeight/2), w: 200, h: 100,
				isResizable: false
			}))
			.appendChild(
				new WindowText({ content: "FILENAME", ww: 1/2, wh: 50 })
			)
			.appendChild(
				new WindowTextField({ ww: 1/2, wh: 50,
					setValue: x => { fileName = x },
					getValue: () => fileName
				})
			)
			.appendChild(
				new WindowButton({ ww: 1 , wh: 20,
					content: "SAVE",
					callback: () => {
						saveAs(new File([this.saveSetupToJSON()], "JAMS-"+fileName+".json", {type: "data:application/json;charset=utf-8"}));
					}
				})
			)
		)
	}

	openSetup() {
		setTimeout(() => { /**remove canvas drag listener**/ },100);
		var opener = document.createElement("input");
		opener.type = "file";
		opener.accept = ".json";
		opener.addEventListener('change', (e) => {
			if(!e.target.files[0] || e.target.files[0].name.substr(-5).toLowerCase() !== ".json") return;
			var reader = new FileReader();
			reader.onload = (e) => {
				this.loadSetup(e.target.result);
			}
			reader.readAsText(e.target.files[0]);

		});
		opener.click();
	}

	openSetupFromUrl (url) {
		let win = this.alert("Loading Setup...");
		fetch(url).then(response => {
			if (response.ok)
				return response.text()
			this.alert("Failed loading setup from URL");
		}).then(data => {
			this.loadSetup(data);
			win.close();
		});
	}

	alert 		(message, title = "Alert") { //this is synonymous to window.alert of the DOM
		let win = new InterfaceWindow({
				x: ~~(innerWidth/2), y: ~~(innerHeight/2),
				w: 370, h: 100,
				title: title
			});

			win
			.appendChild(new WindowText({
				ww: 1, wh: 30,
				content: message,
				fontSize: 1
			}))
			.appendChild(new WindowButton({
				ww: 1, wh: 30,
				content: "OK!",
				fontSize: 1,
				callback: () => win.close()
			}));

			this.interface.add(win);
		return win;
	}

	saveSetupToJSON() {
		var setup = [];
		this.modules.forEach( module => {
			var inputsArr = [];
			module.inputs.forEach( (input,ind) => {
				inputsArr[ind] = {
					id : input.id,
					index : input.index
				}
			});

			let params = module.params.map( p => {
				if (!p.paramSave) {
					return p.value;
				} else {
					return p.paramSave(p.value);
				}
			});

			setup.push({
				id: module.id,
				type: module.className,
				x: module.x,
				y: module.y,
				inputs: inputsArr,
				params: params,
				name: module.name
			})
		});
		return JSON.stringify(setup);
	}

	loadSetup		(json) {
		let _ = this;
		this.newSetup();
		let setup = JSON.parse(json);
		try {
			setup.forEach( module => {
				_.moduleCounter = Math.max(_.moduleCounter, module.id);
				try {
					var mod = _.createModule(module.x, module.y, Modules[module.type], module.id);
				} catch(e) {
					console.warn(e);
					module.invalid = true;
					console.warn("Possible that " + module.type + " is not a valid module");
					return;
				}
				mod.name = module.name || "";
				module.params.forEach( (val, ind) => {
						if(!mod.params[ind].paramLoad)
							mod.setParam(ind, val);
						else
							mod.setParam(ind, mod.params[ind].paramLoad(val));
				});

				if(module.type == "Output") {
					_.deleteModule(_.outputModule);
					_.outputModule = mod;
				}
			})
			setup.forEach( module => {
				let targetModule = _.getModuleFromId(module.id);
				if(targetModule == undefined) return;
				module.inputs.forEach( (input,index) => {
					if( input == null ) return;
					let sourceModule = _.getModuleFromId(input.id);
					if( sourceModule == undefined ) return;
					sourceModule.connect(targetModule, index, input.index);
				})
			});
		} catch(e) {
			console.error("Corrupted Setup File: ", e); return;
		}
	}

}<|endoftext|>


<commit_before>'use strict';

module.exports = function(grunt) {
  require('time-grunt')(grunt);
  require('load-grunt-tasks')(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    phplint: {
      options: {
        swapPath: '/tmp'
      },
      application: [
        '<%= dirs.src %>/**/*.php',
        '<%= dirs.tests %>/**/*.php'
      ]
    },
    phpcs: {
      options: {
        bin: 'vendor/bin/phpcs',
        standard: 'PSR2'
      },
      application: {
        dir: [
          '<%= dirs.src %>',
          '<%= dirs.tests %>'
        ]
      }
    },
    phpmd: {
      options: {
        bin: 'vendor/bin/phpmd',
        rulesets: 'unusedcode,naming,design,controversial,codesize',
        reportFormat: 'text'
      },
      application: {
        dir: '<%= dirs.src %>'
      }
    },
    phpcpd: {
      options: {
        bin: 'vendor/bin/phpcpd',
        quiet: false,
        ignoreExitCode: true
      },
      application: {
        dir: '<%= dirs.src %>'
      }
    },
    climb: {
      options: {
        bin: 'vendor/bin/climb'
      },
      application: {
      }
    },
    security_checker: {
      options: {
        bin: 'vendor/bin/security-checker'
      },
      application: {
        file: 'composer.lock'
      }
    },
    phpunit: {
      options: {
        bin: 'vendor/bin/phpunit',
        coverage: true
      },
      application: {
        coverageHtml: '<%= dirs.dist %>/coverage'
      }
    }
  });

  grunt.registerTask('check', ['phplint', 'phpcs', 'phpmd', 'phpcpd']);
  grunt.registerTask('security', ['climb', 'security_checker']);
  grunt.registerTask('test', ['phpunit']);

  grunt.task.registerTask('build', 'Project build', function() {
    grunt.log.writeln('Task ready to be implemented');
  });

  grunt.registerTask('default', ['check', 'security', 'test']);
};
<commit_msg>define format<commit_after>'use strict';

module.exports = function(grunt) {
  require('time-grunt')(grunt);
  require('load-grunt-tasks')(grunt);

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    phplint: {
      options: {
        swapPath: '/tmp'
      },
      application: [
        '<%= dirs.src %>/**/*.php',
        '<%= dirs.tests %>/**/*.php'
      ]
    },
    phpcs: {
      options: {
        bin: 'vendor/bin/phpcs',
        standard: 'PSR2'
      },
      application: {
        dir: [
          '<%= dirs.src %>',
          '<%= dirs.tests %>'
        ]
      }
    },
    phpmd: {
      options: {
        bin: 'vendor/bin/phpmd',
        rulesets: 'unusedcode,naming,design,controversial,codesize',
        reportFormat: 'text'
      },
      application: {
        dir: '<%= dirs.src %>'
      }
    },
    phpcpd: {
      options: {
        bin: 'vendor/bin/phpcpd',
        quiet: false,
        ignoreExitCode: true
      },
      application: {
        dir: '<%= dirs.src %>'
      }
    },
    climb: {
      options: {
        bin: 'vendor/bin/climb'
      },
      application: {
      }
    },
    security_checker: {
      options: {
        bin: 'vendor/bin/security-checker',
        format: 'text'
      },
      application: {
        file: 'composer.lock'
      }
    },
    phpunit: {
      options: {
        bin: 'vendor/bin/phpunit',
        coverage: true
      },
      application: {
        coverageHtml: '<%= dirs.dist %>/coverage'
      }
    }
  });

  grunt.registerTask('check', ['phplint', 'phpcs', 'phpmd', 'phpcpd']);
  grunt.registerTask('security', ['climb', 'security_checker']);
  grunt.registerTask('test', ['phpunit']);

  grunt.task.registerTask('build', 'Project build', function() {
    grunt.log.writeln('Task ready to be implemented');
  });

  grunt.registerTask('default', ['check', 'security', 'test']);
};
<|endoftext|>


<commit_before>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

module.exports = function(grunt) {

  // Fix grunt options
  // Can remove if using grunt 0.5
  // https://github.com/gruntjs/grunt/issues/908
  require('nopt-grunt-fix')(grunt);

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Load the Flow XO tasks
  grunt.loadNpmTasks('flowxo-sdk');

  // Define the configuration for all the tasks
  grunt.initConfig({
    env: {
      src: '.env'
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          quiet: false,
          clearRequireCache: false,
          require: './tests/helpers'
        },
        src: ['tests/bootstrap.js', 'tests/**/*.spec.js']
      }
    },
    watch: {
      js: {
        options: {
          spawn: true,
          interrupt: false,
          debounceDelay: 250
        },
        files: ['lib/**/*.js', 'tests/**/*.spec.js'],
        tasks: ['jshint', 'test']
      }
    },
    jshint: {
      options: {
        jshintrc: true,
        reporter: require('jshint-stylish')
      },
      source: {
        src: ['Gruntfile.js', 'lib/**/*.js']
      },
      tests: {
        src: ['tests/**/*.js'],
      }
    },
    jsbeautifier: {
      options: {
        config: '.jsbeautifyrc'
      },
      source: {
        src: ['Gruntfile.js', 'lib/**/*.js']
      },
      tests: {
        src: ['tests/**/*.js'],
      }
    },
    flowxo: {
      options: {
        credentialsFile: 'credentials.json',
        getService: function() {
          return require('./lib');
        },
      },
      init: {},
      auth: {},
      run: {
        options: {
          runsFolder: 'runs',
        }
      }
    }
  });

  // Initialise the SDK
  grunt.registerTask('init', ['flowxo:init']);

  // Authentication Tasks
  grunt.registerTask('auth', ['env', 'flowxo:auth']);

  // Run Tasks
  grunt.registerTask('run', ['env', 'flowxo:run']);

  // Test Tasks
  grunt.registerTask('test', ['env', 'mochaTest']);

  // Default Task
  grunt.registerTask('default', ['env', 'jsbeautifier', 'jshint', 'test', 'watch']);
};
<commit_msg>Added configuration for webhook port<commit_after>// Generated on <%= (new Date).toISOString().split('T')[0] %> using <%= pkg.name %> <%= pkg.version %>
'use strict';

module.exports = function(grunt) {

  // Fix grunt options
  // Can remove if using grunt 0.5
  // https://github.com/gruntjs/grunt/issues/908
  require('nopt-grunt-fix')(grunt);

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Load the Flow XO tasks
  grunt.loadNpmTasks('flowxo-sdk');

  // Define the configuration for all the tasks
  grunt.initConfig({
    env: {
      src: '.env'
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec',
          quiet: false,
          clearRequireCache: false,
          require: './tests/helpers'
        },
        src: ['tests/bootstrap.js', 'tests/**/*.spec.js']
      }
    },
    watch: {
      js: {
        options: {
          spawn: true,
          interrupt: false,
          debounceDelay: 250
        },
        files: ['lib/**/*.js', 'tests/**/*.spec.js'],
        tasks: ['jshint', 'test']
      }
    },
    jshint: {
      options: {
        jshintrc: true,
        reporter: require('jshint-stylish')
      },
      source: {
        src: ['Gruntfile.js', 'lib/**/*.js']
      },
      tests: {
        src: ['tests/**/*.js'],
      }
    },
    jsbeautifier: {
      options: {
        config: '.jsbeautifyrc'
      },
      source: {
        src: ['Gruntfile.js', 'lib/**/*.js']
      },
      tests: {
        src: ['tests/**/*.js'],
      }
    },
    flowxo: {
      options: {
        credentialsFile: 'credentials.json',
        getService: function() {
          return require('./lib');
        },
      },
      init: {},
      auth: {},
      run: {
        options: {
          runsFolder: 'runs',
          webhookPort: 9095
        }
      }
    }
  });

  // Initialise the SDK
  grunt.registerTask('init', ['flowxo:init']);

  // Authentication Tasks
  grunt.registerTask('auth', ['env', 'flowxo:auth']);

  // Run Tasks
  grunt.registerTask('run', ['env', 'flowxo:run']);

  // Test Tasks
  grunt.registerTask('test', ['env', 'mochaTest']);

  // Default Task
  grunt.registerTask('default', ['env', 'jsbeautifier', 'jshint', 'test', 'watch']);
};
<|endoftext|>


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

  angular.module('myApp.beers', ['ngRoute'])

  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/beers', {
      templateUrl: 'modules/beers/beers.html',
      controller: 'BeersCtrl'
    });
  }])

  .controller('BeersCtrl', BeersCtrl);

  function BeersCtrl($scope) {
    $scope.msg = 'Listagem das cervejas';
    $scope.reverse = false;
    $scope.predicate = 'name';

    $scope.ordenar = function(predicate) {
      $scope.predicate = predicate;
      $scope.reverse = !$scope.reverse
    }
  // criamos um array de cervejas
    var cervejas = [{
      name: 'Kaiser', price: 2
      }, {
        name: 'Skol', price: 3
      }, {
        name: 'Glacial', price: 4
      }, {
        name: 'Polar', price: 6
      }, {
        name: 'Heineken', price: 10
      }
    ];
  // instanciamos nosso array no nosso scope
  // para que tenhamos acesso à esse array na View
    $scope.cervejas = cervejas;
  }

  BeersCtrl.$inject = ['$scope'];

})();<commit_msg>LIstando cervejas via API do Node<commit_after>(function() {
  'use strict';

  angular.module('myApp.beers', ['ngRoute'])

  .config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/beers', {
      templateUrl: 'modules/beers/beers.html',
      controller: 'BeersCtrl'
    });
  }])

  .controller('BeersCtrl', BeersCtrl);

  function BeersCtrl($scope, $http) {
    $scope.msg = 'Listagem das cervejas';
    $scope.reverse = false;
    $scope.predicate = 'name';

    $scope.ordenar = function(predicate) {
      $scope.predicate = predicate;
      $scope.reverse = !$scope.reverse
    }

    var url = 'http://localhost:3000/api/beers'
      , method = 'GET'
      ;

    $http({
      url: url
    , method: method
    })
    .success(function(data) {
      $scope.cervejas = data;
      console.log('Sucesso', data);
    })
    .error(function(data) {
      console.log('Erro: ', data);
    });

  }

  BeersCtrl.$inject = ['$scope', '$http'];

})();<|endoftext|>


<commit_before>google.setOnLoadCallback(drawChart);

function drawChart() {
  var flu_data = [];
  flu_data.week = [35, 36, 37, 38, 39, 49, 49, 49, 49, 44, 45, 46, 47, 48, 49, 50, 51, 52, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34];

  flu_data.hospital = [0, 0, 0, 0, 3, 2, 2, 1, 2, 5.5, 6.5, 6.5, 12.5, 31, 44, 66.5, 113, 163.5, 181, 129, 118.5, 109, 108.5, 102.5, 102.5, 121.5, 121.5, 149, 152, 121.5, 94.5, 60.5, 73.5, 42.5, 36, 32.5, 22.5, 18, 8, 3.5, 4, 1, 1, 0, 0, 1.5, 1.5, 0, 0, 0, 0, 1];

  flu_data.death = [0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 1, 0.5, 2.5, 5.5, 8, 13, 11.5, 9.5, 14.5, 9, 7, 5.5, 4.5, 8.5, 8.5, 7.5, 8.5, 9, 4, 3, 2.5, 2.5, 2, 1, 1, 1.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0];

  thisWeek = getCurrentWeek();

  var splitData = [];

  var i = 0,
	  soFar = 0,
	  left = 0;
  while (flu_data.week[i] != thisWeek) {
	  soFar += flu_data.death[i];
	  splitData.push([i, flu_data.death[i], 0]);
	  i++;
  }
  splitData.push([i - 1, 0, flu_data.death[i - 1]]);

  //Keep incrementing "i" with second graph for futur deaths
  for (; i < 52; i++) {
	  left += flu_data.death[i];
	  splitData.push([i, 0, flu_data.death[i]]);
  }

  var data = new google.visualization.DataTable();
  //google.visualization.arrayToDataTable(splitData);
  data.addColumn('number', 'Week');
  data.addColumn('number', 'Deaths so far');
  data.addColumn('number', 'Deaths to come');

  data.addRows(splitData);

  var options = {
	  width: 400,
	  height: 240,
	  title: 'Reported deaths in Canada from influenza in 2010-2011 by this week',
	  hAxis: {
		  ticks: [{v: 3, f: 'September'},{v: 12, f: 'November'},{v: 20, f: 'January'},{v: 29, f: 'March'},{v: 38, f: 'May'},{v: 46, f: 'July'}]
	  },
	  vAxis: {
		  minValue: 0
	  },
	  legend: {
		  position: 'none'
	  },
	  colors: ['orange', 'red']
  };
	/*
  var dataView = new google.visualization.DataView(data);
  dataView.setColumns([{calc: function(data, row) { return ''; }, type:'string'}, 2, 1,0]);
  */
  var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
  chart.draw(data, options);
}

function getCurrentDay() {
  var now = new Date();
  var start = new Date(now.getFullYear(), 0, 0);
  var diff = now - start;
  var oneDay = 1000 * 60 * 60 * 24;
  return Math.floor(diff / oneDay);
}

function getCurrentWeek() {
  return Math.min(Math.floor(getCurrentDay() / 7) + 1, 52);
}<commit_msg>Removing fixed width<commit_after>google.setOnLoadCallback(drawChart);

function drawChart() {
  var flu_data = [];
  flu_data.week = [35, 36, 37, 38, 39, 49, 49, 49, 49, 44, 45, 46, 47, 48, 49, 50, 51, 52, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34];

  flu_data.hospital = [0, 0, 0, 0, 3, 2, 2, 1, 2, 5.5, 6.5, 6.5, 12.5, 31, 44, 66.5, 113, 163.5, 181, 129, 118.5, 109, 108.5, 102.5, 102.5, 121.5, 121.5, 149, 152, 121.5, 94.5, 60.5, 73.5, 42.5, 36, 32.5, 22.5, 18, 8, 3.5, 4, 1, 1, 0, 0, 1.5, 1.5, 0, 0, 0, 0, 1];

  flu_data.death = [0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0, 0.5, 0, 0.5, 1, 0.5, 2.5, 5.5, 8, 13, 11.5, 9.5, 14.5, 9, 7, 5.5, 4.5, 8.5, 8.5, 7.5, 8.5, 9, 4, 3, 2.5, 2.5, 2, 1, 1, 1.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0.5, 0, 0, 0, 0];

  thisWeek = getCurrentWeek();

  var splitData = [];

  var i = 0,
	  soFar = 0,
	  left = 0;
  while (flu_data.week[i] != thisWeek) {
	  soFar += flu_data.death[i];
	  splitData.push([i, flu_data.death[i], 0]);
	  i++;
  }
  splitData.push([i - 1, 0, flu_data.death[i - 1]]);

  //Keep incrementing "i" with second graph for futur deaths
  for (; i < 52; i++) {
	  left += flu_data.death[i];
	  splitData.push([i, 0, flu_data.death[i]]);
  }

  var data = new google.visualization.DataTable();
  //google.visualization.arrayToDataTable(splitData);
  data.addColumn('number', 'Week');
  data.addColumn('number', 'Deaths so far');
  data.addColumn('number', 'Deaths to come');

  data.addRows(splitData);

  var options = {

	  height: 240,
	  title: 'Reported deaths in Canada from influenza in 2010-2011 by this week',
	  hAxis: {
		  ticks: [{v: 3, f: 'September'},{v: 12, f: 'November'},{v: 20, f: 'January'},{v: 29, f: 'March'},{v: 38, f: 'May'},{v: 46, f: 'July'}]
	  },
	  vAxis: {
		  minValue: 0
	  },
	  legend: {
		  position: 'none'
	  },
	  colors: ['orange', 'red']
  };
	/*
  var dataView = new google.visualization.DataView(data);
  dataView.setColumns([{calc: function(data, row) { return ''; }, type:'string'}, 2, 1,0]);
  */
  var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
  chart.draw(data, options);
}

function getCurrentDay() {
  var now = new Date();
  var start = new Date(now.getFullYear(), 0, 0);
  var diff = now - start;
  var oneDay = 1000 * 60 * 60 * 24;
  return Math.floor(diff / oneDay);
}

function getCurrentWeek() {
  return Math.min(Math.floor(getCurrentDay() / 7) + 1, 52);
}<|endoftext|>


<commit_before>
//Defino funcion constructora wikiController para crear objeto y seleccionar los elementos
function WikiController(tapiz, guardar, editar){

    this.tapiz = document.getElementById(tapiz);

    this.guardar = document.getElementById(guardar);

    this.editar = document.getElementById(editar);

}

//Defino funcion constructora Wiki para crear ojetos de su subtipo
//@id id de la wiki.
//@styles estilos de la wiki
//@sitax sintasis de la wiki
function Wiki(id, styles, sintax){

    this.id = id;

    this.styles = {
        'width': '100%',
        'height': '400px',
        'border': '1px solid blue'
    };

    //Array con sintaxis de la Wiki para comparar con los strings recogidos del textarea
    this.sintax = [
        sections = "=",
        articles = "-",
        divs     = "#",
        back     = "*",
        linksInit = "[",
        linksFin = "]",
        linksToInit  = "(",
        linksToFin   = ""
    ];

    //metodo de insertar textarea en el tapiz para el modo edicion.
    //@id identificador de la wiki a editar (ya lo tenemos al crear el objeto).
    this.insertarTextarea = function(id){
        var textarea = document.createElement("textarea");
        textarea.id = "area1";
        textarea.rows = 20;
        textarea.cols = 100;
        //aplicarEstilos(textarea, estilos);
        tapiz.appendChild(textarea);

        // return ...el return ha de colocar el cursor en el textarea directamente e incluir en el textarea el contenido guardado.
    };

    //Metodo para recoger datos de la wiki
    //@id identificador de la wiki de la que hay que recoger los datos.
    this.recogerWiki = function(id){};

    //Metodo de guardar en JSON las cadenas de texto recogidas en el textarea.
    //@id identificador a guardar (ya lo tenemos al crear el objeto)
    this.guardarTextarea = function(id){
        var area = document.getElementById('area1');
        console.log(area);
        //var areaText = area.nodeValue; //da element input no el nodo de texto.
        //var childrenTextarea = area.childNodes; //da 0 nodos hijos??
        var text = new String(area.value); //variable de tipo string, nos interesa objeto ??

        //Pruebas de atributos de area
        var textString = area.value;
        console.log(textString);
        console.log(text);

        var sections = splitSections(text);

        //Metodo que convertirá el textarea y compara los simbolos de la sintaxis de la wiki para formatear la vista de la wiki.
        function splitSections(string){
            var arraySections = new Array();
            var count = 0;
            var lastCount;

            //Recorro el string para detectar las secciones
            for (var i = 0; i< string.length; i++) {
                var t = i + 2;

                //Cuando tengo 3 = seguidos, estoy en una section...
                if(string[i] == "=" && string[i++] == "=" && string[t] == "="){
                    lastCount = count;
                    count = count+1;

                    //Creo un objeto en el array, en el indice numerico en el que estoy
                    arraySections[count] = {};
                    //El id será igual al inidice del array
                    arraySections[count].id = count;
                    //El inicio del título de la section es en el que estoy ahora mismo.
                    arraySections[count].startHeader = i;

                    //Si he detectado otra seccion, como no es la ultima le establezco el fin de la anterior
                    if(count > 1){
                        arraySections[lastCount].fin = i -1;
                    }

                    console.log(i);
                    //Localizo el salto de líne posterior al lugar en el que estoy.
                    var nextSalto = string.indexOf("\n",i);

                    console.log(nextSalto);

                    //Guardo el header en el objeto de section
                    arraySections[count].header = string.substring(i+3, nextSalto);

                    arraySections[count].startSection = nextSalto+1;

                    //Guardo en cada objeto section la cadena restante en bruto y sin título
                    if(count > 1){
                        arraySections[lastCount].section = string.substring(arraySections[lastCount].startSection, arraySections[lastCount].fin );
                        console.log(arraySections[lastCount].section);
                    }

                    //console.log(arraySections[lastCount].section);

                }
            }

            // Y cuando salgo del for le agrego al ultimo objeto su fin que sera el fin del String
            arraySections[count].fin = string.length;

            //cuando sale del for también aprobecho para guardar el último section
            arraySections[count].section = string.substring(arraySections[count].startSection, arraySections[count].fin);

            console.log(arraySections);
            //var strings = string.split(caracter);
            return arraySections;
        };

        //console.log(sections);

       // return el return ha de llamar a convertirTextarea para guardarla en formato convertido
       return sections;
    };

    //Metodo que aplica una lista de estilos a un elemento.
    //@element elemento a aplicar los estilos
    //@listaEstilos estilos a aplicar al elemento.
    this.aplicarEstilos = function (elemento, listaEstilos){
        for (var estilo in listaEstilos ){
            elemento.style[estilo] = listaEstilos[estilo];
        }
    };

};

function crearObjWiki(id){
    //TODO:consultar previamente el id correspondiente
    var wiki = new Wiki(id);
    return wiki;

};

var wikiCtl = new WikiController("tapiz", "guardar", "editar" );
var wiki = new Wiki(1, {}, []);

//window.onload = ;
editar.onclick = wiki.insertarTextarea;
guardar.onclick = wiki.guardarTextarea;
<commit_msg>Sustiidos los saltos de line \n por el simbolo ¬ para que se guarden en el string section<commit_after>
//Defino funcion constructora wikiController para crear objeto y seleccionar los elementos
function WikiController(tapiz, guardar, editar){

    this.tapiz = document.getElementById(tapiz);

    this.guardar = document.getElementById(guardar);

    this.editar = document.getElementById(editar);

}

//Defino funcion constructora Wiki para crear ojetos de su subtipo
//@id id de la wiki.
//@styles estilos de la wiki
//@sitax sintasis de la wiki
function Wiki(id, styles, sintax){

    this.id = id;

    this.styles = {
        'width': '100%',
        'height': '400px',
        'border': '1px solid blue'
    };

    //Array con sintaxis de la Wiki para comparar con los strings recogidos del textarea
    this.sintax = [
        sections = "=",
        articles = "-",
        divs     = "#",
        back     = "*",
        linksInit = "[",
        linksFin = "]",
        linksToInit  = "(",
        linksToFin   = ""
    ];

    //metodo de insertar textarea en el tapiz para el modo edicion.
    //@id identificador de la wiki a editar (ya lo tenemos al crear el objeto).
    this.insertarTextarea = function(id){
        var textarea = document.createElement("textarea");
        textarea.id = "area1";
        textarea.rows = 20;
        textarea.cols = 100;
        //aplicarEstilos(textarea, estilos);
        tapiz.appendChild(textarea);

        // return ...el return ha de colocar el cursor en el textarea directamente e incluir en el textarea el contenido guardado.
    };

    //Metodo para recoger datos de la wiki
    //@id identificador de la wiki de la que hay que recoger los datos.
    this.recogerWiki = function(id){};

    //Metodo de guardar en JSON las cadenas de texto recogidas en el textarea.
    //@id identificador a guardar (ya lo tenemos al crear el objeto)
    this.guardarTextarea = function(id){
        var area = document.getElementById('area1');
        console.log(area);
        //var areaText = area.nodeValue; //da element input no el nodo de texto.
        //var childrenTextarea = area.childNodes; //da 0 nodos hijos??
        var text = new String(area.value); //variable de tipo string, nos interesa objeto ??

        //Pruebas de atributos de area
        var textString = area.value;
        console.log(textString);
        console.log(text);

        var sections = splitSections(text);

        //Metodo que convertirá el textarea y compara los simbolos de la sintaxis de la wiki para formatear la vista de la wiki.
        function splitSections(cadena){
            var arraySections = new Array();
            var count = 0;
            var lastCount;

            //sustituyo los saltos de linea por el simnbolo ¬
            //(parace que el parser de JS no lo guarda y después no dispongo de esos saltos en el string)
            var string = cadena.replace(new RegExp("\n", "g"), "¬");

            //Recorro el string para detectar las secciones
            for (var i = 0; i< string.length; i++) {
                var t = i + 2;

                //Cuando tengo 3 = seguidos, estoy en una section...
                if(string[i] == "=" && string[i++] == "=" && string[t] == "="){
                    lastCount = count;
                    count = count+1;

                    //Creo un objeto en el array, en el indice numerico en el que estoy
                    arraySections[count] = {};
                    //El id será igual al inidice del array
                    arraySections[count].id = count;
                    //El inicio del título de la section es en el que estoy ahora mismo.
                    arraySections[count].startHeader = i;

                    //Si he detectado otra seccion, como no es la ultima le establezco el fin de la anterior
                    if(count > 1){
                        arraySections[lastCount].fin = i -1;
                    }

                    console.log(i);
                    //Localizo el salto de líne posterior al lugar en el que estoy.
                    var nextSalto = string.indexOf("¬",i);

                    console.log(nextSalto);

                    //Guardo el header en el objeto de section
                    arraySections[count].header = string.substring(i+3, nextSalto);

                    arraySections[count].startSection = nextSalto+1;

                    //Guardo en cada objeto section la cadena restante en bruto y sin título
                    if(count > 1){
                        arraySections[lastCount].section = string.substring(arraySections[lastCount].startSection, arraySections[lastCount].fin );
                        console.log(arraySections[lastCount].section);
                    }

                    //console.log(arraySections[lastCount].section);

                }
            }

            // Y cuando salgo del for le agrego al ultimo objeto su fin que sera el fin del String
            arraySections[count].fin = string.length;

            //cuando sale del for también aprobecho para guardar el último section
            arraySections[count].section = string.substring(arraySections[count].startSection, arraySections[count].fin);

            console.log(arraySections);
            //var strings = string.split(caracter);
            return arraySections;
        };

        //console.log(sections);

       // return el return ha de llamar a convertirTextarea para guardarla en formato convertido
       return sections;
    };

    //Metodo que aplica una lista de estilos a un elemento.
    //@element elemento a aplicar los estilos
    //@listaEstilos estilos a aplicar al elemento.
    this.aplicarEstilos = function (elemento, listaEstilos){
        for (var estilo in listaEstilos ){
            elemento.style[estilo] = listaEstilos[estilo];
        }
    };

};

function crearObjWiki(id){
    //TODO:consultar previamente el id correspondiente
    var wiki = new Wiki(id);
    return wiki;

};

var wikiCtl = new WikiController("tapiz", "guardar", "editar" );
var wiki = new Wiki(1, {}, []);

//window.onload = ;
editar.onclick = wiki.insertarTextarea;
guardar.onclick = wiki.guardarTextarea;
<|endoftext|>


<commit_before>CircleBlvd.Services.lib = function () {

    var LabelRegex = /[:;,<> \\\{\[\(\?\.\`\'\"\*\)\]\}\/]/;
    var ReplaceLabelRegex = /[#:;,<> \\\{\[\(\?\.\`\'\"\*\)\]\}\/]/g;

    return {
        consts: {
            ReplaceLabelRegex: ReplaceLabelRegex,
            LabelRegex: LabelRegex
        }
    };
};
CircleBlvd.Services.lib.$inject = [];<commit_msg>Fix: Labels: Ignore exclamation points<commit_after>CircleBlvd.Services.lib = function () {

    var LabelRegex = /[:;,<> \\\{\[\(\!\?\.\`\'\"\*\)\]\}\/]/;
    var ReplaceLabelRegex = /[#:;,<> \\\{\[\(\!\?\.\`\'\"\*\)\]\}\/]/g;

    return {
        consts: {
            ReplaceLabelRegex: ReplaceLabelRegex,
            LabelRegex: LabelRegex
        }
    };
};
CircleBlvd.Services.lib.$inject = [];<|endoftext|>


<commit_before>/* jshint devel:true */
/* global exports, require */
var findEdges = require('./findedges').findEdges;
exports.graphOptions = {
  'nodes': {
    'brokenImage': 'images/unknown.png'
  },
  'edges': {
    'style' : 'arrow',
    'color.highlight': 'red'
  },
  'stabilize': true,
  'zoomExtentOnStabilize': true
};
exports.collectData = function(json) {
  'use strict';
  var data = { nodes:[], edges:[] };
  var knownResources = [];
  var possibleEdges = [];
  var addEdge = function (toId, title){
    possibleEdges.push( {'from': resourceKey, 'to': toId, 'title': title } );
  };
  for (var resourceKey in json.Resources) {
    var resource = json.Resources[resourceKey];
    var props = resource.Properties;
    var group = resource.Type.toLowerCase().replace(/::/g,'-');
    knownResources.push(resourceKey);
    data.nodes.push({
      'id'   : resourceKey,
      'label': resourceKey,
      'group': group,
      'shape': 'image',
      'image': 'images/' + group + '.png'
    });
    findEdges(props, addEdge);
  }
  data.edges = possibleEdges.filter(function(edge) {
    return edge && knownResources.indexOf(edge.to) >= 0;
  });
  return data;
};

exports.collectCyData = function(json) {
  'use strict';
  var edgeFilters = {
    'AWS::EC2::SecurityGroupIngress': function(edge /*, source, target*/){
      if (edge.data.resource === 'GroupId') {
        // NOOP the direction is good
      }
      else if (edge.data.resource === 'SourceSecurityGroupId') {
        var newTarget = edge.data.source;
        edge.data.source = edge.data.target;
        edge.data.target = newTarget;
      }
      return true;
    },
    'AWS::EC2::SecurityGroupEgress': function(edge /*, source, target*/) {
      if (edge.data.resource === 'DestinationSecurityGroupId') {
        // NOOP the direction is good
      }
      else if (edge.data.resource === 'GroupId') {
        var newTarget = edge.data.source;
        edge.data.source = edge.data.target;
        edge.data.target = newTarget;
      }
      return true;
    },
    'default': function(edge, source, target) {
      if (target && target.type === 'AWS::EC2::SecurityGroup'){
        knownResources[edge.data.source].data.parent = edge.data.target;
        return false;
      }
      return true;
    },
    'get': function(awsType) {
      return this[awsType] || this['default'];
    }
  };
  var data = { nodes:[], edges:[] };
  var edgeIndex = 0;

  var addEdge = function (toId, title, resource) {
    data.edges.push({ data: { id: 'e'+ (edgeIndex++), source: resourceKey, target: toId, title: title, resource: resource }});
  };

  var knownResources = {};
  for (var resourceKey in json.Resources) {
    var resource = json.Resources[resourceKey];
    var r = {
      data: {
        id: resourceKey
      },
      classes: resource.Type.toLowerCase().replace(/::/g,'-'),
      type: resource.Type
    };
    findEdges(resource.Properties, addEdge);
    knownResources[resourceKey] = r;
    data.nodes.push(r);
  }

  data.edges = data.edges.filter(function(edge) {
    var source = knownResources[edge.data.source];
    var target = knownResources[edge.data.target];
    var filter = edgeFilters.get(source.type);
    return edge && source && target && filter(edge, source, target);
  });

  return data;
};
<commit_msg>introduced variable to figure out a way to refactor graph data collection<commit_after>/* jshint devel:true */
/* global exports, require */
var findEdges = require('./findedges').findEdges;
exports.graphOptions = {
  'nodes': {
    'brokenImage': 'images/unknown.png'
  },
  'edges': {
    'style' : 'arrow',
    'color.highlight': 'red'
  },
  'stabilize': true,
  'zoomExtentOnStabilize': true
};
exports.collectData = function(json) {
  'use strict';
  var data = { nodes:[], edges:[] };
  var knownResources = [];
  var possibleEdges = [];
  var addEdge = function (toId, title){
    possibleEdges.push( {'from': resourceKey, 'to': toId, 'title': title } );
  };
  for (var resourceKey in json.Resources) {
    var resource = json.Resources[resourceKey];
    var props = resource.Properties;
    var group = resource.Type.toLowerCase().replace(/::/g,'-');
    knownResources.push(resourceKey);
    data.nodes.push({
      'id'   : resourceKey,
      'label': resourceKey,
      'group': group,
      'shape': 'image',
      'image': 'images/' + group + '.png'
    });
    findEdges(props, addEdge);
  }
  data.edges = possibleEdges.filter(function(edge) {
    return edge && knownResources.indexOf(edge.to) >= 0;
  });
  return data;
};

exports.collectCyData = function(json) {
  'use strict';
  var edgeFilters = {
    'AWS::EC2::SecurityGroupIngress': function(edge /*, source, target*/){
      if (edge.data.resource === 'GroupId') {
        // NOOP the direction is good
      }
      else if (edge.data.resource === 'SourceSecurityGroupId') {
        var newTarget = edge.data.source;
        edge.data.source = edge.data.target;
        edge.data.target = newTarget;
      }
      return true;
    },
    'AWS::EC2::SecurityGroupEgress': function(edge /*, source, target*/) {
      if (edge.data.resource === 'DestinationSecurityGroupId') {
        // NOOP the direction is good
      }
      else if (edge.data.resource === 'GroupId') {
        var newTarget = edge.data.source;
        edge.data.source = edge.data.target;
        edge.data.target = newTarget;
      }
      return true;
    },
    'default': function(edge, source, target) {
      if (target && target.type === 'AWS::EC2::SecurityGroup'){
        knownResources[edge.data.source].data.parent = edge.data.target;
        return false;
      }
      return true;
    },
    'get': function(awsType) {
      return this[awsType] || this['default'];
    }
  };
  var data = { nodes:[], edges:[] };
  var edgeIndex = 0;

  var addEdge = function (toId, title, resource) {
    possibleEdges.push({ data: { id: 'e'+ (edgeIndex++), source: resourceKey, target: toId, title: title, resource: resource }});
  };

  var knownResources = {};
  var possibleEdges = [];

  for (var resourceKey in json.Resources) {
    var resource = json.Resources[resourceKey];
    var r = {
      data: {
        id: resourceKey
      },
      classes: resource.Type.toLowerCase().replace(/::/g,'-'),
      type: resource.Type
    };
    findEdges(resource.Properties, addEdge);
    knownResources[resourceKey] = r;
    data.nodes.push(r);
  }

  data.edges = possibleEdges.filter(function(edge) {
    var source = knownResources[edge.data.source];
    var target = knownResources[edge.data.target];
    var filter = edgeFilters.get(source.type);
    return edge && source && target && filter(edge, source, target);
  });

  return data;
};
<|endoftext|>


<commit_before>/*jshint camelcase:false */
define(function (require) {
    'use strict';

    var client = require('api').getDefaultInstance();
    var Q = require('q');

    function DataBridge(mediator) {
        this.mediator = mediator;
    }

    DataBridge.prototype.listen = function () {
        this.mediator.subscribe('uiLogin', this.login.bind(this));
        this.mediator.subscribe('uiLogout', this.logout.bind(this));
        this.mediator.subscribe('uiRefreshCTLs', this.refreshCTLs.bind(this));
        this.mediator.subscribe('uiResolveCTL', this.resolveCTL.bind(this));
        this.mediator.subscribe('uiCreateCTL', this.createCTL.bind(this));
        this.mediator.subscribe('uiOverwriteCTL', this.overwriteCTL.bind(this));
        this.mediator.subscribe('uiUserInfo', this.getUserInfo.bind(this));

        this.mediator.subscribe('dataResolveCTLPartial', this.resolveCTL.bind(this));
    };

    DataBridge.prototype.login = function () {
        client.login();
    };

    DataBridge.prototype.logout = function (data) {
        client.logout().then(function () {
            this.mediator.publish('dataLogout', {
                key: data.key
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'uiLogout',
                status: e.status,
                message: 'Logging out failed',
                data: {}
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.getUserInfo = function (data) {
        client.getUser(data.id).then(
            function (response) {
            this.mediator.publish('dataUserInfo', {
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'uiUserInfo',
                status: e.status,
                message: 'Fetching user information failed.',
                data: data
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.resolveCTL = function (data) {
        var options = {
            include_cards: 1,
            send_error_codes: 1,
            include_entites: 1
        };

        client.getCTL(data.id, options).then(function (response) {
            this.mediator.publish('dataResolveCTL', {
                ctl: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'resolveCTL',
                status: e.status,
                message: 'Resolving CLT failed.',
                data: data
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.createCTL = function (data) {
        function handleProgress(mediator, progress) {
            console.log('Progress reported: ', progress);
            mediator.publish('dataCreateCTLProgress', progress);
        }

        client.createCTL({
            name: data.name,
            description: data.description
        }, data.tweetIds || [], handleProgress.bind(this, this.mediator))
        .then(function (response) {

            this.mediator.publish('dataCreateCTL', {
                // To identify the response
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'createCTL',
                status: e.status,
                message: 'Creating CTL or attaching Tweets failed.',
                data: data
            });
        }.bind(this)).done();
    };

    /**
     * Overwrites the Tweets in an existing CTL.
     *
     * Expects data.id in addition to what createCtl expects.
     */
    DataBridge.prototype.overwriteCTL = function (data) {
        var promises = [];
        var updates = _.pick(data, ['description', 'name']);

        function handleProgress(mediator, progress) {
            mediator.publish('dataOverwriteCTLProgress', progress);
        }

        promises.push(client.overwriteCTL(
            data.id, data.tweetIds, handleProgress.bind(this, this.mediator)
        ));

        if (!_.isEmpty(updates)) {
            promises.push(client.updateCTL(data.id, updates));
        }

        // Execute both in parallel, but wait for them to finish before
        // returning.
        Q.all(promises).then(function (responses) {
            this.mediator.publish('dataOverwriteCTL', {
                key: data.key,
                response: responses[0]
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'overwriteCTL',
                status: e.status,
                message: 'Fetching or overwriting CTL failed.',
                data: data
            });
        }.bind(this)).done();
    };

    /**
     * Refreshes all CTLs for the given `userId`.
     */
    DataBridge.prototype.refreshCTLs = function (data) {
        client.getCTLs({
            userId: data.userId,
            sendErrorCodes: true
        }).then(function (response) {
            this.mediator.publish('dataCTLs', {
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'refreshCTLs',
                status: e.status,
                message: 'Refreshing CTLs failed.',
                data: data
            });
        });
    };

    return DataBridge;
});
<commit_msg>Add missing lodash import<commit_after>/*jshint camelcase:false */
define(function (require) {
    'use strict';

    var client = require('api').getDefaultInstance();
    var Q = require('q');
    var _ = require('lodash');

    function DataBridge(mediator) {
        this.mediator = mediator;
    }

    DataBridge.prototype.listen = function () {
        this.mediator.subscribe('uiLogin', this.login.bind(this));
        this.mediator.subscribe('uiLogout', this.logout.bind(this));
        this.mediator.subscribe('uiRefreshCTLs', this.refreshCTLs.bind(this));
        this.mediator.subscribe('uiResolveCTL', this.resolveCTL.bind(this));
        this.mediator.subscribe('uiCreateCTL', this.createCTL.bind(this));
        this.mediator.subscribe('uiOverwriteCTL', this.overwriteCTL.bind(this));
        this.mediator.subscribe('uiUserInfo', this.getUserInfo.bind(this));

        this.mediator.subscribe('dataResolveCTLPartial', this.resolveCTL.bind(this));
    };

    DataBridge.prototype.login = function () {
        client.login();
    };

    DataBridge.prototype.logout = function (data) {
        client.logout().then(function () {
            this.mediator.publish('dataLogout', {
                key: data.key
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'uiLogout',
                status: e.status,
                message: 'Logging out failed',
                data: {}
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.getUserInfo = function (data) {
        client.getUser(data.id).then(
            function (response) {
            this.mediator.publish('dataUserInfo', {
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'uiUserInfo',
                status: e.status,
                message: 'Fetching user information failed.',
                data: data
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.resolveCTL = function (data) {
        var options = {
            include_cards: 1,
            send_error_codes: 1,
            include_entites: 1
        };

        client.getCTL(data.id, options).then(function (response) {
            this.mediator.publish('dataResolveCTL', {
                ctl: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'resolveCTL',
                status: e.status,
                message: 'Resolving CLT failed.',
                data: data
            });
        }.bind(this)).done();
    };

    DataBridge.prototype.createCTL = function (data) {
        function handleProgress(mediator, progress) {
            console.log('Progress reported: ', progress);
            mediator.publish('dataCreateCTLProgress', progress);
        }

        client.createCTL({
            name: data.name,
            description: data.description
        }, data.tweetIds || [], handleProgress.bind(this, this.mediator))
        .then(function (response) {

            this.mediator.publish('dataCreateCTL', {
                // To identify the response
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'createCTL',
                status: e.status,
                message: 'Creating CTL or attaching Tweets failed.',
                data: data
            });
        }.bind(this)).done();
    };

    /**
     * Overwrites the Tweets in an existing CTL.
     *
     * Expects data.id in addition to what createCtl expects.
     */
    DataBridge.prototype.overwriteCTL = function (data) {
        var promises = [];
        var updates = _.pick(data, ['description', 'name']);

        function handleProgress(mediator, progress) {
            mediator.publish('dataOverwriteCTLProgress', progress);
        }

        promises.push(client.overwriteCTL(
            data.id, data.tweetIds, handleProgress.bind(this, this.mediator)
        ));

        if (!_.isEmpty(updates)) {
            promises.push(client.updateCTL(data.id, updates));
        }

        // Execute both in parallel, but wait for them to finish before
        // returning.
        Q.all(promises).then(function (responses) {
            this.mediator.publish('dataOverwriteCTL', {
                key: data.key,
                response: responses[0]
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'overwriteCTL',
                status: e.status,
                message: 'Fetching or overwriting CTL failed.',
                data: data
            });
        }.bind(this)).done();
    };

    /**
     * Refreshes all CTLs for the given `userId`.
     */
    DataBridge.prototype.refreshCTLs = function (data) {
        client.getCTLs({
            userId: data.userId,
            sendErrorCodes: true
        }).then(function (response) {
            this.mediator.publish('dataCTLs', {
                key: data.key,
                response: response
            });
        }.bind(this), function (e) {
            this.mediator.publish('dataError', {
                method: 'refreshCTLs',
                status: e.status,
                message: 'Refreshing CTLs failed.',
                data: data
            });
        });
    };

    return DataBridge;
});
<|endoftext|>